Part Number Hot Search : 
ACHIP 015015 NJU7601 NTD4860N CT3805 AO4800L IRFP244A AP1045A
Product Description
Full Text Search
 

To Download AN1075 Datasheet File

  If you can't view the Datasheet, Please click here to try to view without PDF Reader .  
 
 


  Datasheet File OCR Text:
  AN1075/1098 1/98 application note using the st9+ memory management unit (examples for st92195 and st92r195) by microcontroller division applications introduction this application note describes techniques for creating software applications using the memory management unit (mmu) of the st9+. in addition, it provides useful hints on using the st9+ c compiler. a description of the main characteristics of the st9+ mmu will be given. then, the c compiler will be briefly described, emphasizing the memory management unit aspects. finally, the sub- ject matter is developed using examples for a romless and a rom microcontroller, the st92r195 and the st92195 respectively. after reading this document you should be able to understand the key features of the mmu, how to manipulate the different mmu pointers and develop a software application on any st9+ in a secure way with version v4.2 of the st9+ gnu c compiler. to better understand and apply the features implemented in this application note, both a knowledge of the st9+ architecture and the gnu c compiler for st9+ are necessary. 1
2/98 table of contents 98 2 introduction . . . . . . . . . . . ............................................1 1 definitions and abbreviations . . . . . . . . . . . . . .......................5 2 a brief tour of the st9+ mmu . . . . . . . . . . . . ..........................6 2.1 theinstructionsetandthemmu..............................6 2.1.1 instruction cycle times . . . . ............................................8 2.1.2 new st9+ instructions summary . . . . . . . . . . . .............................9 2.1.3 theuserflag ......................................................9 2.2 interrupts and the mmu . . ...................................10 2.3 thememorymanagementunit ................................10 2.3.1 theneedforanmmu ...............................................11 2.3.2 accessing functions . . . . . . . . . . . . . ...................................12 2.3.3 accessing the data . .................................................13 2.3.4 swapping the dprs and the pdrs . . . . . . . ..............................14 2.3.5 the bootrom ......................................................15 2.4 external memory interface . . . . . . . . . . . . . . . . . . ...............15 2.5 program/data selection . . . . . . . . . . . . .........................16 2.5.1 spm /sdm and the standard instructions . . . . . ...........................16 2.5.2 the stacks . . . . . . . . . . . . . . ..........................................17 2.5.3 lddd, ldpd, lddp, ldpp instructions . . . . .............................18 2.5.4 interrupts and the program/data management . . . . . . . . . . ..................20 3thev4.2st9+gnuccompiler .....................................21 3.1 v4.2 gnu c compiler features at a glance . . .................21 3.2 optionstouse ...............................................21 3.2.1 compiler options . . . . ...............................................21 3.2.2 linker options . . . . .................................................22 3.3 howtomanagethemmuwiththecompiler ..................22 3.3.1 mmu models handled by the v4.2 compiler . . . ...........................22 3.3.2 managing functions .................................................22 3.3.3 managing data . . . . . ................................................23 3.4 mapping your application with the linker . . .................23 3.4.1 the possible data/code sections and their mapping . . . .....................23 3.4.2 notes on using initialized variables . . . . . . . ..............................26 3.4.3 a tentative set of general rules . . . . ....................................28 3.5 summary of v4.2 st9+ gnu c compiler limitations .............29
3/98 table of contents 4 first example: the st92195 . . . . . . . . . . . . ............................30 4.1 memorymapping .............................................30 4.2 description of the application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31 4.3 mmu settings on the st92195 . . . . . . . . . . . . . . . . . . ...............31 4.4 mapping the application with the scriptfile . . . . . . . . . . . . . . . . . 33 4.5 initialized variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 4.6 compiler and linker options . . . . .............................38 4.7 application files . . . . . . . . . . . . . ...............................38 4.8 emulator configuration file . . . . . . . . . . . . . . . . . . . . . ...........39 5secondexample:thest92r195 ....................................40 5.1 st92r195 memory mapping . . . . ................................40 5.2 application description . . ...................................41 5.3 managing functions . . . . . . . . . . . . . ............................41 5.3.1 using function pointers . . ............................................42 5.4 managing data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ........47 5.4.1 c and assembly directives for managing the data. . . . ......................49 5.4.2 managing the data pointer changes. . . . . . . ..............................49 5.4.3 data page registers and port data registers . . . . . . . .....................51 5.5 mapping the application with the scriptfile . . . . . . . . . . . . . . . . . 52 5.6 libraries . . . . . . . . . . . . . . . . . . . . . ................................54 5.7 thecompilerandlinkeroptions ............................54 5.8 application files . . . . . . . . . . . . . ...............................55 5.9 the debugger configuration file . . . . . . . . . . . . ................55 3
4/98 table of contents 98 6appendix-sourcefiles ..........................................56 6.1 common source files . . ......................................56 6.1.1 define.h . . . . . . . . . . . . . . ..........................................56 6.1.2 mmu.h...........................................................57 6.1.3 st9macro.h . . . . . ................................................60 6.1.4 display.h .......................................................61 6.2 the first application example source files : the st92195 . . . . 62 6.2.1 main.c ..........................................................62 6.2.2 actions.c .......................................................66 6.2.3 const.c.........................................................68 6.2.4 display.c .......................................................70 6.3 the second application example source files : the st92r195 78 6.3.1 main.c ..........................................................78 6.3.2 const.c.........................................................89 6.3.3 menu1.c.........................................................90 6.3.4 menu2.c.........................................................90 6.3.5 code04.c ........................................................91 4
5/98 definitions and abbreviations 1 definitions and abbreviations far function: a function that is defined in a 64k segment, and that can be called by a func- tion from another 64k segment. this function is ended by the rets instruction. far call: a call to a function located in a different 64k segment mmu : memory management unit bankswitch: an st9 pointing mechanism for managing large code applications physical address: a 22-bit address used to access the physical internal or external mem- ory. logical address: a 16-bit address, used in instructions, that is translated into a physical ad- dress for accessing physical memory.
6/98 a brief tour of the st9+ mmu 2 a brief tour of the st9+ mmu this section gives a summary of the key features of the st9+ mmu. 2.1 the instruction set and the mmu the st9+ instruction set is fully compatible with the st9. this means that all applications run- ning on st9 may be run on st9+. in fact, the instruction set of the st9 has been improved in the st9+ to increase its power in terms of speed, code size, and debug support. also, the mmu allows you to easily implement applications with large code size using dedicated instruc- tions for accessing far objects. the new st9+ instructions are: link this instruction was added to reduce c function transfer overhead. it implements the prologue of a c function, that needs to reserve a defined number of bytes in system stack for passing parameters and local variables. the operation performed for each c function in a prologue is: pushw rr12 step (1) ldw rr12, sspr step (2) subw sspr, #n step (3) thus, this would represent 9 bytes per prologue and 36 clock cycles. it can now be done by: link rr12, #n which takes 3 bytes and 16/12 clock cycles depending if the stack is in the register file or in memory. unlink this instruction is used in the epilogue of the c function, which is equivalent to the comple- ment of the link instruction. it is also made for reducing the code size overhead and increase the execution speed of the c functions. the unlink replaces: ldw sspr, rr12 popw rr12 and is used by doing: unlink rr12 in this case the amount of bytes saved is 2 and the number of clock cycles is between 14 and 18, depending on whether the stack is in the register file or in memory.
7/98 a brief tour of the st9+ mmu linku - same as link instruction for the user stack unlinku - same the unlink instruction for the user stack jps the jps instruction is an inter-segment jump. this means that this instruction does a jump to a specified offset inside a specified page. for example: rr0 = 3000h r2 = 20h jps (rr0), r2 will do a jump to segment 20h at address 3000h inside this 64k segment calls the calls instruction allows you to do an inter-section call, that is a call to a function that is located in a different 64k segment. for example: rr0 = 3000h r2 = 20h calls (rr0), r2 will call the function pointed to by rr0 in segment 20h. note that the calls stacks both the return address, and the current segment number. rets the rets instruction is used to return from a function that is called by the calls instruction. it restores both the return address, and the segment to return to. note that it is used simply as rets, without source or destination parameters. warning : if a function is ended by a rets, then all calls to this function should be done by the calls instruction. otherwise, if a call instruction is done, it will only stack the return ad- dress, but the rets instruction will try to restore both the return address and the segment number.
8/98 a brief tour of the st9+ mmu 2.1.1 instruction cycle times instruction cycle times have been optimized in the st9+ core to increase the cpu speed. you should be aware that even if the source code is fully compatible with the st9 core, if rou- tines use delay loops based on instruction cycle times, they will have to be modified. an exhaustive list of the differences will not be given here. you should refer to the st9+ pro- gramming manual to get this information. as a guideline, you can consider that, with the same external clock, the speed increase of the st9+ is about x1.5, compared to the st9 instruction set. this evaluation is based on general routines written in assembler or c. however, it is important to know that the difference is spe- cific to each instruction. for example: or r,r lasts 6 clock cycles on st9 and only 4 clock cycles on st9+, but rlcw rr lasts 8 clock cycles on st9 and also 8 clock cycles on st9+.
9/98 a brief tour of the st9+ mmu 2.1.2 new st9+ instructions summary 2.1.3 the user flag the user flag (uf) present on st9 is no longer available to the user. this flag was bit 1 of the flagr (r231) register in the system register group. this flag is now reserved for emulation purposes. in a normal user application, reading or writing to this bit has no effect. however, if the application is run on the emulator, writing to this bit is prohibited. it will stop the emulator and an error message saying that an access that tried to write to this register will be displayed. thus, it is advised make write accesses to the flagr only with or or and instructions, for ex- ample: or r231,#00000001b <= to set only bit 0 and r231,#00000010b <= to reset all bits except bit1 the uf user flag instruction operands size (bytes) clock cycles comment jps (r),(rr) (r),(rr) n,nn 3.00 10.00 inter-segment jump calls (r),(rr) (r),(rr) n,nn 4.00 16.00 inter-segment call to a subroutine rets 2.00 12/10 inter-segment return from a subroutine link rr, #nrr, #n 3.00 16/12 adjust stack and frame pointer in a prologue func- tion when using the system stack for parameter passing unlink rr,rr 3.00 10/6 adjust stack and frame pointer in an epilogue func- tion when using the system stack for parameter passing linku rr, #nrr, #n 3.00 16/12 adjust stack and frame pointer in a prologue func- tion when using the user stack for parameter pass- ing unlinku rr,rr 3.00 10/6 adjust stack and frame pointer in an epilogue func- tion when using the user stack for parameter pass- ing
10/98 a brief tour of the st9+ mmu 2.2 interrupts and the mmu there are some differences between the st9 and st9+ interrupts. the first main difference is that in st9 instructions cannot be interrupted by the cpu. in the st9+, instructions can be in- terrupted if they have not already modified the memory or the register file. also an option bit allows you to configure two different ways of handling interrupts, depending on an option bit encpr , located in the emr2 register of the memory management unit. in order to simplify the understanding of this, it can be considered that, by default, the behav- iour of the interrupt handling in the st9+ is fully compatible to the one in the st9. there is however one restriction to the mmu: it is not possible to use far calls (calls) inside an interrupt service routine. so, for example, on an mcu with only 64k of program memory like the st92e195, there is no difference between st9 and st9+. on st9+, a specific register is dedicated to pointing to the interrupt service routines. this 16-bit register isr (stands for interrupt segment register) always points to a user de- fined 64k segment, where the interrupt vectors and interrupt service routines should be lo- cated. then depending on the encpr option bit, there are 2 cases: encpr = 0 when entering into the interrupt service routine, isr is simply used instead of csr. this is st9 compatible. in this case, it is not possible to use far calls in interrupt service rou- tine because the csr is not stacked. only the return address (16-bit) and the flags (8-bit) are saved into the system stack. encpr = 1 csr is first pushed onto the stack and then takes the value of the isr register. in this case the interrupt stacks both the return address (16-bit), the segment (8-bit) and the flags (8-bit). refer to the memory management unit chapter of any st9+ datasheet for more information. warning: if you need to use the large code model (with more than 64k of code), then all func- tions will be automatically defined as far functions by the compiler. in this case you will have to use the large model for interrupts too (encpr = 1), i.e. because interrupt routines that use far functions must imperatively use the large model. 2.3 the memory management unit this section will not describe the mmu completely, but will try to highlight the key points needed to fully understand the examples, and the requirements imposed on the compiler.
11/98 a brief tour of the st9+ mmu 2.3.1 the need for an mmu the st9 is a 16-bit address cpu, which means that only 64k linear memory blocks can be ac- cessed. to remove this limitation, a mechanism, the obankswitcho, was used in the st9 to access up to 8 mbytes of code. this mechanism was based on a segmentation of the memory into two types: a static block (32k): accessible at any time several dynamic blocks (32k): accessible only through a specific sequence in static block. there was no specific instruction to access dynamic blocks and the access was user defined, always via the static bank. this static bank being only 32k wide, the restriction was important. to get around these restrictions and to access more than 64k of memory more easily and ef- ficiently, while keeping the fast and cost-effective architecture of the st9, the memory man- agement unit was built. this mmu allows you to access up to 4 mbytes (22-bit address) of code in an almost linear manner, that is through specific instructions, providing a transparent way of managing func- tions. data are pointed to by four data pointers that can address the whole 4 mbyte memory range. seen in a simplified way, in the st9+ we now have 22-bit addressing (16+6 bits) for code and data accesses. code addresses are almost linear and data addresses are paginated.
12/98 a brief tour of the st9+ mmu 2.3.2 accessing functions a 6-bit register, the csr (code segment register) is dedicated to pointing to the 64 kbyte segment in use. modification of this register is done only through 3 instructions: jps , calls and rets . thus, to access a function located in a different segment, you must use the calls or jps in- structions. these instructions modify the csr value, pointing to the new segment to access and jump to the offset specified. if a calls is done, both the return address and the old csr value will be stacked. keep in mind that if a function is called with calls it must be ended by a rets to keep the stack frame coherent (the standard call instruction stacks only the return address, not the csr). warning : it is prohibited to modify the csr directly, using standard instructions. only calls , and jps can modify it! any modification of this register will completely lose control of the segment location, and therefore program counter may not point to the correct segment. two different cases are now presented to the user: the application uses less than 64k of program: no impact on the software, all functions are called with the call instruction and are ended by ret. the application uses more than 64k of program: with the compiler, it will be seen later on, that only far functions (calls, rets) will be used, except for static functions, that are normal functions (call, ret).
13/98 a brief tour of the st9+ mmu 2.3.3 accessing the data to properly understand data management with the mmu, we must consider 2 types of ad- dresses for the same data: the physical address: this is the address that is effectively put onto the memory bus (22- bit). this address is the concatenation of the 14 least significant bits of the logical address and the 8 bits of one of the 4 data page registers (dpr0-3). the logical address: this is the address that will be given to the instruction (16-bit). it is only 16 bits long. the identification of which data pointer will be used to recreate the physical ad- dress is made through the 15th and 14th bits, according to the following table: thus, any instruction that uses a 16-bit address between: 0x0000 and 0x3fff will select dpr0 0x4000 and 0x7fff will select dpr1 0x8000 and 0xcfff will select dpr2 0xd000 and 0xffff will select dpr3 it will also be seen later on, that the linker allows you to force a data object to be accessed by a specific dpr, whatever its physical address. any dpr can point to any 16 kbyte page of any 64 kbyte segment. the logical address se- lects both which dpr to use (15th and 14th bits), and the 14-bit offset inside a block of 16 kbytes. in this way, with a fixed logical address, by selecting the proper dpr value, it is possible to ac- cess 256 different locations in the 4 mbyte memory (8 bits of the dpr). 15th bit 14th bit dpr selected 000 011 102 113
14/98 a brief tour of the st9+ mmu for example: if the logical address of foo is 1000100010001000b (0x8888), then bits 15 and 14 select dpr2 (10) automatically. the offset inside the 16 kbyte page, pointed to by dpr2 is 0x0888 (14 least significant bits of foo). if dpr2 = 00100001b (0x21), the physical address obtained is: xx00 1000 1000 1000 => logical address (without 15 & 14th bits) 0010 0001 => dpr value replaces 15 & 14th bits ____________________________ + the 6 most significant bits xx00 1000 0100 1000 1000 1000 => physical address is 0x084888 ^^ ||______________ these bits are don't care (only 22-bit address) to summarize the management of data pointers in the mmu: these are the main things to re- member: a logical address selects both one dpr and an offset inside the 16 kbyte page pointed to by this dpr. the physical address is made of the 8 bits of the dpr shifted by 2 (to replace the 15th & 14th bits of the 16-bit virtual address), concatenated with the 14 least significant bits of the logical address. a dpr can point to any of the 16 kbyte pages of memory in the 4 mbyte address range. the linker will allow a data object to be pointed to by any dpr, whatever its physical address. 2.3.4 swapping the dprs and the pdrs it is important to note also that the mmu allows you to map the dprs either in register group e of the register file, or in register group f, page 21. this is a user selection that is done through an option bit dprrem (stands for dpr remap- ping) of register emr2 (see external memory registers). if the dprs are located in register group e, then the port data registers are located in group f, page 21, at the same address as the dprs. this is what is meant when we say that they are swapped with the dprs. this option allows you to have easy access (without changing the register page) either to the data pointer register or the data port registers. this is because you can choose to map the registers that will require the most frequent accesses in group e. in our examples we will only consider the case where the dprs are located in group f of page 21. this is also the default setting at mcu reset.
15/98 a brief tour of the st9+ mmu 2.3.5 the bootrom the bootrom is a piece of code (64 bytes) located in segment 21h. it is always internal to the mcu, and performs different internal settings depending on the device. after reset, the first instructions executed are the ones contained in the bootrom. an important thing to note is that depending on the device, the bootrom will set the dprs to a certain location, for example in the st92195, dpr0-1 point to page 0h and 1h (internal rom), dpr2 points to page 8ah (seg 22h) where the tdsram is located, and dpr3 points to page 83h (seg 20h) where the ram is located. the bootrom code also reads the user reset vector and jumps (far jump) to the reset routine. the bootrom code should be transparent to the user. 2.4 external memory interface for this part it is crucial to refer to the external memory interface chapter of the st9+ device datasheet for complete information. note, however that some st9+ devices do not have an external memory bus. important facts to bear in mind are: in the st9+, memory accesses are only 2 clock cycles long, they were 3 clock cycles long on st9 - timing accesses should be carefully studied when building your application. 0 to 3 wait states on ds (data strobe) and as (address strobe) have been added for slow external memories. these wait states are in addition to the wait states on program memory and data memory previously present on st9 (see also the description of the wcr register in the datasheet) various memory bus options can be selected through the emr1 and emr2 registers located in page 21 of register file group f.
16/98 a brief tour of the st9+ mmu 2.5 program/data selection on the st9, a pin was dedicated to the selection of program memory and data memory. due to the fact it was a physical pin, both memories had to be physically distinct. on the st9+, this pin has been removed and distinction between the program (opcode fetch) and the data accesses is done through the mmu. this allows you to have a single physical memory where both code and data can reside. the program (the code) is accessed using the csr register pointer, while the data is ac- cessed using the dprs . note that it is possible to have the csr pointing to a segment and one (or more) dprs pointing to the same memory location. so all memories are accessible as data or code, and code can thus be executed in ram. we can separate instructions into three types: standard instructions (ld, or, and, ...), they are affected by spm/sdm instructions and use either the dpr or scr registers. stack instructions, always using the dprs program flow instructions (jp, call), always using the csr 2.5.1 spm /sdm and the standard instructions the sdm and spm instructions are still valid on st9+. we will see later that only the sdm in- struction must used and spm should not be used anymore. the effect of using these instructions is the following: when sdm precedes an instruction, the data is accessed through the selected dpr(0-3) . when spm precedes an instruction, the data is accessed through the csr . for example: suppose: csr = 00h <= code register points to segment 0h dpr0 = 00h <= dpr0 points to seg 0, page 0 dpr1 = 01h <= dpr1 points to seg 0, page 1 dpr2 = 02h <= dpr2 points to seg 0, page 2 dpr3 = 83h <= dpr3 points to seg 20h, page 3
17/98 a brief tour of the st9+ mmu first case: instruction sdm has been used before this code sequence. address: instruction 0xnnnn sdm ........... ......... .......... .......... 0xafde ld r0, f000h is equivalent to: 0xafde 0xc4f0f000 the program counter will read address 0xafde, in the segment pointed to by the csr, i.e. segment 0h, and will access the data located in f000h in segment 20h using dpr3 (because 15th & 14th bits are 1 & 1 respectively). second case: instruction spm has been used before this code sequence. address: instruction 0xnnnn spm ........... ......... .......... .......... 0xafde ld r0, f000h the program counter will read address 0xafde, in the segment pointed to by csr, i.e. seg- ment 0h, and will access the data located in f000h in segment 0h using the csr (because of spm instruction). 2.5.2 the stacks a stack is always considered as data, whatever the sdm/spm instruction was preceding a stack access through push/pop instructions. this was already the case in the st9. if a stack instruction is executed, it will always use the dpr to access the memory. selection of the dpr uses the same process as for standard data. for example: the same settings as in the previous example are used for the csr and dprs. first case: the sdm instruction has been used before this code sequence. address: instruction 0xnnnn sdm ........... ......... 0xmmmm ldw rr238, #0ff00h .......... .......... 0xafde push r0 0xafe0 ld r0, f000h
18/98 a brief tour of the st9+ mmu the program counter will read address 0xafde, in the segment pointed to by csr, i.e. seg- ment 0h, and will push r0 to address ff00h in segment 20h using dpr3 (because the 15th & 14th bits are 1 & 1 respectively). the access to data at f000h also uses dpr3. second case: the spm instruction has been used before this code sequence. 0xnnnn spm ........... ......... 0xmmmm ldw rr238, #0ff00h .......... .......... 0xafde push r0 0xafe0 ld r0, f000h the program counter will read address 0xafde, in the segment pointed to by csr, i.e. seg- ment 0h, and push r0 to address ff00h in segment 20h using dpr3 (because the 15th & 14th bits are 1 & 1 respectively). the access to data at f000h uses csr, so a read from seg- ment 0h, offset f000h is done. this mechanism is valid for both user and system stacks. 2.5.3 lddd, ldpd, lddp, ldpp instructions the specific instructions use the same mechanism as previously described. lddd : source and destination are accessed through the 2 dprs selected ldpd: source is accessed using dpr and destination is accessed through csr lddp: source is accessed using csr and destination is accessed through dpr ldpp: source is accessed using csr and destination is accessed through csr for example whatever the sdm/spm status is before the following instructions, and assuming the same set- tings for csr/dprs as in the previous example. before the instruction the memory contains: segment 0h: address f000h contains aah address f020h contains bbh segment 20h address f000h contains cch address f020h contains ddh lddd instructions ldw rr0, #0f000h ldw rr2, #0f020h lddd (rr0)+,(rr2)+
19/98 a brief tour of the st9+ mmu after the instruction, the memory contains: segment 0h: address f000h contains aah address f020h contains bbh segment 20h address f000h contains ddh address f020h contains ddh ldpd instruction ldw rr0, #0f000h ldw rr2, #0f020h ldpd (rr0)+,(rr2)+ after the instruction, the memory contains: segment 0h: address f000h contains ddh address f020h contains bbh segment 20h address f000h contains cch address f020h contains ddh lddp instruction ldw rr0, #0f000h ldw rr2, #0f020h lddp (rr0)+,(rr2)+ after the instruction, the memory contains: segment 0h: address f000h contains aah address f020h contains bbh segment 20h address f000h contains bbh address f020h contains ddh ldpp instruction ldw rr0, #0f000h ldw rr2, #0f020h ldpp (rr0)+,(rr2)+ after the instruction, the memory contains: segment 0h: address f000h contains bbh address f020h contains bbh segment 20h address f000h contains ddh address f020h contains ddh
20/98 a brief tour of the st9+ mmu 2.5.4 interrupts and the program/data management depending on the memory model you choose when you compile and link the application, the compiler will use sdm/spm instructions or not. on st9+, the only model available is with the -mpd option, which tells the compiler that pro- gram and data memories are distinct. in this configuration, the c compiler generates spm/sdm instructions only in the following cases: switch statements: during the switch statement, the compiler sometimes needs to access tables located in rom (.text section). it thus needs to perform an spm, then access the table, and return to the previous state by doing an sdm interrupt service routines: an interrupt can occur at any time, and it is possible to enter an interrupt service routine just after executing an spm instruction. so, the c compiler generates an sdm instruction at the very beginning of a c interrupt service routine. for the same reason, if an interrupt service routine is written in assembly it is strongly advised to put an sdm at the very beginning of the interrupt routine. conclusion: it is strongly advised to place an sdm instruction at the very beginning of the pro- gram and never use the spm/sdm inside the program again, except for an interrupt service routine written in assembler.
21/98 the v4.2 st9+ gnu c compiler 3 the v4.2 st9+ gnu c compiler this section does not provide comprehensive information on the compiler. you are advised to read the st9+ gnu c toolchain release 4.2 note. most of the information in this section has been directly extracted from this document and you will sometimes find more features docu- mented than those given here. here we will only focus on the following points: st9+ mcu only, not the st9 compatibility new important options the different mappings allowed by the compiler 3.1 v4.2 gnu c compiler features at a glance runs on windows nt, windows 95, windows 3.x and dos. st9 and st9+ compatible with different options. only tiny and small data memory models available. improved linker for managing mmu data pointers: the script file syntax supports new features for managing data and program memory blocks. implementation of st9+ new instructions. set of assembly and c macros to facilitate mmu usage optimization improvements 3.2 options to use in this part of the application note we will only consider the st9+ mcu. thus, only the impor- tant options will be described. 3.2.1 compiler options -mfar: this option is used if more than 64 kbytes of code are used in the application. it de- fines all functions as far, except static functions. -mlink: this option will implement the prologue and epilogue of the c functions using the new link/unlink instructions. -mpd : this option, present on previous versions, specifies that a 2-memory model is used. it is a default option, and must be used on st9+. -tr9: this option is to include tr9 in the compilation. by default tr9 is no longer called when compiling a c file, and this option is needed only if macro-assembly is used inside the appli- cation (c or assembly files).
22/98 the v4.2 st9+ gnu c compiler 3.2.2 linker options in this application note, the linker will always use a scriptfile. the only new and important op- tion is thus: -mmu: this option allows relocation of the data object through the dpr registers. it is also needed to have access to the mmu macros defined in c or assembly. 3.3 how to manage the mmu with the compiler the first thing you should do is evaluate which of the mmu memory models provided by the v4.2 compiler is needed by your application. 3.3.1 mmu models handled by the v4.2 compiler two memory models can be handled by the compiler and linker: total size of code and data is less than 64 kbytes. => in this case the mmu is fully transparent to the user code size is more than 64 kbytes and data size is not taken into account: => in this case the mmu function management is fully handled by the compiler and the data management has to be done manually. however, the compiler provides features like reloca- tion of data objects and several macros to help manage the data. 3.3.2 managing functions if the size of the application code and data does not exceed 64 kbytes, there will be no problem, so only applications that do not fulfil this condition have to be discussed here. if the code size is greater than 64 kbytes, then you have to use the -mfar option. this option will set all functions far, except static functions. the proper libraries are automati- cally linked with the application. far function pointers are not supported by the v4.2 compiler. to allow pointing to functions lo- cated in different segments, some macros are implemented in the sources provided with the compiler. the passing of parameters and return values is also available with the help of macros. it should be noted that as macros are used, and because they don't allow a variable number of arguments, it is not possible to use far function pointers having a variable number of argu- ments. in the following examples, it will be investigated in a first step the case where the code size in smaller than 64 kbytes (st92e195), no far functions will then be needed. in a second case, where the code size is larger than 64 kbytes, and where all functions are far, examples of function pointers will be implemented.
23/98 the v4.2 st9+ gnu c compiler 3.3.3 managing data by default no dpr management is done. depending on the application, and especially if you use more than 64 kbytes of data you will have to manage the data pointers manually. in this way, you can relocate a data object by defining, as a linker option, which data pointer will be selected when accessing the data in c or assembly. for example: if foo is located at physical address 0x200200, its 16-bit address should be 0x0200, and thus only dpr0 should be pointing to foo. then: ld r0, foo<=> ld r0,0x0200 and dpr0 must be set to 0x80 we can tell the linker that foo needs to be pointed to by dpr2 (for example), but keeping foo at the same physical address. then after relocation, the linker uses address 0x8200 (in- stead of 0x0200) to access foo. then: ld r0, foo<=> ld r0, 0x8200 and dpr2 contents must be 0x80 this relocation is very powerful as it allows you to have different blocks of data, pointed to by the same dpr or group of dprs, even if their physical addresses are completely different. then it's up to you to switch the dpr values depending on the data that is accessed. some macros are provided to allow you to retrieve and set the correct dpr value corre- sponding to particular data in a routine. these macros are: pag (symbol) <= returns the physical page number pof(symbol) <= returns the offset inside the 16kbyte memory block (14 bits). for example, before accessing variable var, if it has been relocated with dpr3, it is possible to do: dpr3 = pag(var); var = 0x12; 3.4 mapping your application with the linker in this application note, we advise you to define a scriptfile for each application. the scriptfile is a memory description file that allows you to fine tune the memory mapping. with the script- file, you can locate each section (.text, .data and .bss) of a selected file in a user-defined memory region. 3.4.1 the possible data/code sections and their mapping in st9+, we consider as data, both the uninitialized variables (.bss section), the initialized var- iables (.data section) and the constants (.data section). with the -mpd complier option, there is no difference for the compiler and the linker between constants and initialized variables. they are both located in the .data section.
24/98 the v4.2 st9+ gnu c compiler it is crucial, however, that the constants be kept in non-volatile memory, the initialized varia- bles in volatile memory (to modify them) and the copy of the initial value of the initialized vari- ables in non-volatile memory. thus, the user has to participate in the separation of the constants and the initialized varia- bles. this is possible only by separating the constants and the initialized variables into dif- ferent files (remember the granularity of the linker is at the file level). we therefore advise you generate files dedicated to the definition of the constants, and files dedicated to the initialized variables. the memory scheme obtained is the following: to implement this scheme it is necessary to map the .data section of the files containing the constants, in rom (or any non-volatile) memory region, to map the .data section of the files containing the .data section of the initialized variables into the effective .data section that will have its references in ram. finally it is necessary to have the initial value of the initialized variables in rom. these init values are copied at startup from rom to ram.
25/98 the v4.2 st9+ gnu c compiler for example: suppose: file const.c contains: const unsign ed char constant0[]=othis is an example of constantso; file init.c contains: unsigned char init0[]=othis is an example of an init variableo; the scriptfile should look like: output_arch(st9) memory { rom : origin = 0x000000, length = 64k ram : origin = 0x20ff00, length = 256 } sections { .text : { _text_start = .; reset.o(.text) _start_constants = .; const.o(.data) _end_constants = .; *(.text) _etext = .; do_option_i _text_end = .; }>rom .data : { _data_start = .; init.o(.data) _edata = .; _data_end = .; }>ram .bss : { _bss_start = .; *(.bss common) _ebss = .; _bss_end = . ; }>ram }
26/98 the v4.2 st9+ gnu c compiler 3.4.2 notes on using initialized variables one limitation of the linker is that it is not possible to have more than 64 kbytes of initialized variables in one application. this is due to the fact that the .data section of the linker cannot exceed 64 kbytes. anyway, it is advised not to use any initialized variables, but to use non-initialized variables that are initialized inside a specific routine. also, even if there are no initialized variables in an application, you are advised to separate the constants and variables into dedicated files. this is not a real restriction, and it promotes de- velopment of clean and maintainable software. anonymous strings are also a problem in the compiler, because they are mapped in the .text section, but still need to be pointed to by a dpr. to avoid this, for example, instead of: void func() { printf(ohello worldo); } it is advised to do: const unsigned char foo[] =ohello worldo; unsigned char *pfoo; void func() { pfoo = foo; printf(pfoo); } refer also to the ld9 linker documentation for complete information on scriptfile syntax and capabilities. in the examples given in detail below, the mapping of the data in the script file will be dis- cussed case by case, as various possibilities are available to the user. let us look now at the possibility of relocating the data objects so they can be pointed to by de- fined dprs. the principle is the following: if a data var is to be mapped physically at address 0x200000, it seems obvious that if nothing is done, the logical address of var is 0x0000. consequently, var must use dpr0 to generate the physical address.
27/98 the v4.2 st9+ gnu c compiler suppose that for different reasons, dpr0 needs to point to the 16 kbyte segment starting at address 0x220000, and that no modification of the value of dpr0 is possible (for example dpr0 points to the stack location). in this case you need to point to the var variable with another dpr. this is then implemented in the scriptfile by specifying which dpr points to a particular memory block. for example, suppose we have originally: ram1: origin = 0x200000, length = 16k with the linker of the v4.2 chain, it is possible to specify: ram1: origin = 0x200000, length = 16k, mmu = dpr2 in this case all data are relocated from 0x0000 to 0x3fff to 0x8000 to 0xcfff, and conse- quently the physical addresses will be generated with the dpr2 value. this means that whatever the physical address of a data object, it can use any of the dpr reg- isters. the general syntax for the scriptfile is: name: origin = 22-bit address, length = xx, mmu = dpr list where dpr list can be any one of the following: dpr0, dpr1, dpr2, dpr3, csr, no if no is specified, then no relocation is done. if data is found in the segment, and a reference to this data is made, a warning is generated to tell the user that some data are present in this region, without a specific dpr coverage. if csr is specified, nothing is done (no relocation, no warning). this option is useful if a seg- ment contains only code. if dprx is specified, relocation of the 16 kbytes block is based on dprx. warning: although it is possible to relocate data with the same dpr, inside a 64k segment, you will still have to set the specific dpr to the correct value before accessing the data. to avoid programming errors, you are advised to define blocks of data with the same size as the area that can be covered by the total number of free dprs. that is, for example, if dpr0 and dpr1 are free to access data, then you can define blocks of 32k covered by dpr0 and dpr1 only. note: relocation with dpr registers is done only on .data and .bss sections. you should be aware that if some constants are defined in assembly using for example: .text tab1: .byte 0xaa
28/98 the v4.2 st9+ gnu c compiler then tab1 will not be relocated with specific dprs because it is located in the .text section. in assembly, to allow relocation the following notation should be used: .data tab1: .byte 0xaa and of course, this constant should still be located in a separate file and follow the same map- ping scheme as described previously. 3.4.3 a tentative set of general rules it is difficult to follow general rules for managing the data pointers within an application. it fully depends on the memory mapping of the mcu used, and on the requirements of the memory application. an application will always use: a stack: kept in ram non-initialized variables, kept in ram constants and initial values of initialized variables, mapped in rom code, located in rom: one dpr must be fixed, to always point to the system and user stacks. this is especially true for applications written in c, as most parameters, local variables and return values are ac- cessed through the system or user stacks. in general the stacks don't take more than 16 kbytes of memory, so only one pointer needs to be fixed. for most applications, 16 kbytes of ram is enough, thus only one dpr can be used to access the non-initialized variables and the stacks. the 3 other free dprs, can be either kept grouped together, which allow to treat data memory blocks of 3x16 = 48 kbytes. this case is suitable for large applications having a small amount of ram and very large rom needs. if large amounts of ram are needed, this often means that large data memory transfers are performed, and in this case, one dpr will be used to point to the source, another one to point to the destination of the transfer. the third is free for other resources. if a different memory exists, located in a different region from the ram, for example the 8 kbytes tdsram of the st92e195, one pointer can be dedicated to this memory and the 2 re- maining pointers used for accessing constants. anyway, the dpr allocation needs to be done case by case, and the current v4.2 compiler does not provide an easy and transparent way of doing data management, so it up to the soft- ware programmer to define a dpr allocation strategy that best suits the application needs. the examples described below try to cover the most frequent memory situations that can arise.
29/98 the v4.2 st9+ gnu c compiler 3.5 summary of v4.2 st9+ gnu c compiler limitations no automatic and transparent data management in the large code model, no automatic and transparent function pointer, with the possibility of using macros instead no variable number of arguments in pointers to far functions. constants must be separated from the code and the initialized variables all these limitations should be removed in the next st9+ compiler generation.
30/98 first example: the st92195 4 first example: the st92195 the st92195 is an mcu dedicated to tv applications. it is however very interesting for dem- onstrating the mmu usage because of its specific mem ory mapping, with 3 different on-chip memories, the rom, ram and tdsram. the example will demonstrate a small osd (on screen display) application showing a pos- sible and recommended way of using the mmu with the c compiler v4.2, with such a memory configuration. 4.1 memory mapping the st92195 is a rom device with 64k of rom, 256 bytes of ram and 8k of tdsram (dy- namic ram). the memory mapping is the following: no memory tdsram 8kbytes bootrom reserved ram 256 bytes no memory no memory no memory rom 64kbytes segment x segment 0 segment 20 segment 21 segment 22 segment x 0x000000 0x00ffff 0x200000 0x20ff00 0x20ffff 0x210000 0x21ffff 0x220000 0x227fff 0x228000 0x229fff 0x22a000 0x22ffff no memory
31/98 first example: the st92195 4.2 description of the application the application proposed will display on 3 lines of osd, representing an osd menu. then using an automaton table, specific events will select the different rows of the menu, or will es- cape/enter into the menu. this type of automaton management is a simple way of navigating in menus, and could be ap- plied to any application. to simplify the examples, 5 events where created, representing a user pressing either a key up, or down, or escape, or set_menu. to avoid having to create a keyboard driver, a routine generates random events in a periodic manner. what the example would like to highlight is: managing the 3 different memories: how to select the correct mmu settings constants: how to map and use them initialized variables: how to map and use them the application will physically display the menu on a tv screen if the user has a st92195 de- moboard, or any board able to display the st92195 osd signals. 4.3 mmu settings on the st92195 the memory mapping of the st92195 shows 3 different memory types, firstly the rom where the code, constants, and initial values for the initialized variables should be located, secondly the ram needed for the variables (initialized or uninitialized) and the stack and thirdly, the td- sram used for the osd display. the rom contains only 64 kbytes, so no far calls will be needed, which means that working with functions is completely transparent. the stack and variables are in segment 20h, page 83h. as this memory needs to be accessed at any time there must be a pointer set permanently to this location. dpr3 will thus be as- signed to point to the ram. the tdsram must be accessed for transferring display variables, the characters and at- tributes necessary for the osd. its location is segment 22h, page 8ah. as this memory may also contain teletext data, whose flow is independent of the program flow, it is important to al- ways have a fixed pointer to this memory. dpr2 will be this pointer. for the constants, located in the rom, it is necessary to be more careful. only 2 dprs are left free to access these constants, so 2 choices are possible depending on how many constants are present in the application: less than 32 kbytes of constants are present: =>in this case, it will be sufficient to set the dprs to two 16 kbyte contiguous pages, and to
32/98 first example: the st92195 never modify the dprs during the program execution. for example, it is possible to map all the constants starting from 0x000000 to 0x007ffff, then set dpr0 = 0x00 and dpr1 = 0x01. more than 32 kbytes of constants are needed by the application: => in this case, the dprs will need to be modified. this will have to be done explicitly in the code when necessary. it will also be necessary to split the 64 kbytes segment 0 into two 32 kbyte blocks because of the risk of a data overlapping page 0x01 and 0x02. in our example, only the first case will be developed further. the expected mmu settings will be the following: warning: there is only one region with no dpr coverage, the region 0x008000 to 0x00ffff. it is important to understand this can be a problem only if any data are accessed in this re- gion. the scriptfile can avoid this problem, by defining which regions are uncovered in order to generate a warning during the link phase.
33/98 first example: the st92195 4.4 mapping the application with the scriptfile this mapping will now be set with the help of the scriptfile: the following is the format and list of file description. output_format(oa .out-st9o) output_arch(st9) input(crt9.o const.o actions.o main.o display.o) <=list of the files next is the definition of the memory mapping, forcing the first 32 kbytes of rom to be relo- cated using dpr0 and dpr1, and to signal if the constants are overlapping on the upper 32 kbyte block. memory { /* define your memory mapping */ rom : origin = 0x000000, length = 64k, mmu = dpr0 dpr1 no no ram : origin = 0x20ff00, length = 256, mmu = dpr3 tdsram : origin = 0x228000, length = 8k , mmu = dpr2 no memory osd and txt variables bootrom reserved stacks variables no memory no memory no memory code constants reset vectors segment x segment 0 segment 20 segment 21 segment 22 segment x 0x000000 0x00ffff 0x200000 0x20ff00 0x20ffff 0x210000 0x21ffff 0x220000 0x227fff 0x228000 0x229fff 0x22a000 0x22ffff no memory dpr0 = 0x00 dpr1 = 0x01 dpr3 = 0x83 dpr2 = 0x8a csr = 0
34/98 first example: the st92195 then the .data, .text and .bss sections are defined: sections { _stack_size = defined(_stack_size) ? _stack_size : 40; _user_stack_size = defined(_user_stack_siz e)? _user_stack_size : 40; important: the .text section is defined here. it should be noted that the crt9.o object file contains the reset and interrupt vectors, so this file should be mapped starting at 0x000000. then just after the crt9 file, the files containing the constants are mapped. note that only the .data section of these files is taken, and mapped in a .text section. this is a trick to force the linker to put the constants in rom. the do_option_i is an option that places the initial values of the initialized variables and the end of the .text section in rom. the crt9 file does the recopy of these values to the variables at startup. .text : { _text_start = .; crt9.o(.text) const.o(.data) *(.text) _etext = .; do_option_i; _text_end = .; }>rom as all the constants are now mapped in .text section, mapping the .data section of all other files will then set only the initialized variables in .data. .data :{ _data_start = .; *(.data) _data_end = .; }>ram the .bss section will then contain the stacks and the non initialized variables.
35/98 first example: the st92195 note also that both the .data section and the .bss section are located in ram. .bss : { _bss_start = .; *(.bss common) _ebss =.; _bss_end = .; _stack_start = defined(_stack_start)? _stack_start : .; _stack_end = _stack_start + _stack_size; _user_stack_start = defined(_user_stack_start)? _user_stack_start : _stack_end; _user_stack_end = _user_stack_start + _user_stack_size; }>ram } important: in this example, no variables were allocated to the tdsram. it could have been possible to put both .data or .bss (init or non-init variables) in this memory. however because the tdsram is managed in a special way, you should refer to the st92195 datasheet for in- formation on how to use it. following are the block diagrams obtained for the rom and the ram, according to this map- ping.
36/98 first example: the st92195 the result for the rom is: the ram mapping is: empty 0x000000 0x00ffff crt9.o (.text) reset and interrupt vectors const (.data) all objects left (.text) .data (initial values of initialized variables) _text_start _text_end _etext _const_start _const_end 0x008000 dpr1 = 0x01 dpr0 = 0x00 empty 0x22ff00 all files - non init variables (.bss) all files - init variables (.data) system and user stacks _bss_start _stack_end _stack_start _bss_end dpr3 = 0x83 _data_start _data_end 0x22ffff
37/98 first example: the st92195 4.5 initialized variables the initialized variables have the particularity of having an initial value located in rom. this initial value needs to be copied from rom to ram at startup. this is done in the crt9.asm file by doing: ; init data area ; ldw rr0,#_data_start ; start of run-time data area ldw rr4,#_data_end ; end of run time data area subw rr4,rr0 ; rr4 = length of initialization data jrz no_data ; if empty ldw rr2,#_text_end ; end romed data area subw rr2,rr4 ; start of romed data area init_data: lddp (rr0)+, (rr2)+ ; init data section dwjnz rr4,init_data no_data: as we can see the lddp instruction is used to access a data from the program space (using csr) and load it into the data space (using a dpr). there is thus no possible problem of pointers, because csr = 0 and is always pointing to segment 0. dpr3 = 0x83, and is fixed, thus the ram is always accessible. one initialized variable has been set in the application program, in main.c: char init_var []=o this is an initialized variable o; if you have an st9+ emulator you can to load the st92195.u file do a reset, visualize that the init_var[] table is empty at reset, using the inspect window for example, then after finishing the init_data routine of the crt9.asm file, the init_var table should contain the proper code, that is in ascii o this is an initialized variable o. in this application note, the initialized variables are set directly in the c files. it is advised how- ever to separate them into different files to keep a better control of these variables, and have a cleaner set of source files for future updating.
38/98 first example: the st92195 4.6 compiler and linker options the options used in the application for compiling are: -mlink : use st9+ link/unlink instructions -g : generate debug information -o : use the optimizer -fomit-frame-pointer : avoid usage of frame pointer when not needed -wall : get all possible warnings -tr9 : use tr9 -wall,-ahld : generate a list file the linker options are: -mmu : allow relocation with dprs -m : generate a map file -t : use a scriptfile -v : set verbose mode on 4.7 application files the necessary application files: makefile the file needed to make the application makedep the dependency description file main.c contains the main routine const.c contains the constants definition action.c contains the various automaton routines display.c contains the osd routines crt9.asm the startup file, contains the interrupt vectors, and calls main it also initializes the st9+ correctly st92195.scr the scriptfile, contains the memory mapping description st92195.u the executable needed by the debugger st92195.hex the hexadecimal file needed to program eprom/otps in addition, all header files and some st9 macros are used and defined in: st9macro.h, newreg.h, define.h, display.h, osd_cons.h
39/98 first example: the st92195 4.8 emulator configuration file to configure the memory used on the st92195 emulator version hds2, the user must use the file hardware.gdb provided with the application. this file contains: clear_map map 0x000000 0xffff sr map 0x20fc00 0xffff sw map 0x228000 0x9fff sw chip_reset
40/98 second example: the st92r195 5 second example: the st92r195 the st92r195 is a romless device, capable of accessing up to 4mbytes of memory, through a 16-bit + 6-bit address bus. the st92r195 is dedicated to tv applications and has the same peripherals as the st92195. it is mainly intended for accessing a large external rom and only the 512 bytes on-chip ram. no additional ram should be used. it also contain 8 kbytes of on-chip tdsram for osd dis- play and teletext data storage. 5.1 st92r195 memory mapping no memory tdsram 8kbytes bootrom reserved ram 512 bytes no memory no memory no memory no memory from segment 1 to 19h segment 0 segment 20 segment 21 segment 22 from segment 23h to 39h 0x000000 0x00ffff 0x200000 0x20fd00 0x20ffff 0x210000 0x21ffff 0x220000 0x227fff 0x228000 0x229fff 0x22a000 0x22ffff no memory external memory external memory external memory reserved to internal memory internal memory external memory
41/98 second example: the st92r195 three 64 kbyte blocks are internal: segment 20h: contains the internal ram from 0x20ffd0 to 0x20ffff segment 21h: contains the bootrom, and is reserved for test purposes segment 22h: contains the tdsram from 0x228000 to 0x229fff these 3 segments are fully internal, only the internal memory in segment is accessible to the user. it is thus not possible, for example to use external memory in segment 20h. as only external rom is used, it is clear that both functions and data will require the mmu. 5.2 application description the application displays an osd menu, split into 3 different segments, using an automaton. the events that will successively call the display of the menu management are random, to avoid implementing a user interface. this will involve the following topics in detail: far function management (the functions that call the menus are all far) static function management data pointer management (as the menu lines are located in different blocks) memory mapping for large applications 5.3 managing functions with an application containing more than 64 kbytes of code, and with the v4.2 c compiler, it is only possible to use the large memory model, which defines all functions as far. static functions are automatically called with call and returned with ret . this is normal, as static functions are not called outside of the file where they are defined, and the mapping of a file can not overlap 2 segments, they are thus always called from routines located in same segment. note : when declaring a static function, do not forget to declare the prototype of the static func- tion as well, if the function is called before its definition. otherwise an error message will be generated during the link. if you want to make reference to external functions, defined in an assembly file, these func- tions must be ended with rets and must always be called in the assembly with calls . note : with the calls instruction the code size increases by 1 byte for each call, and the stack is also increased by 1 byte (for stacking csr).
42/98 second example: the st92r195 5.3.1 using function pointers function pointers are not supported by the compiler version v4.2, they will be supported only in the future versions. to workaround this limitation, a solution is to use a structure made of a char and a pointer to a function, then to use a macro for doing the far call to the function. a possible macro is pro- vided in the mmu.h file. what can be obtained is: typedef struct { unsigned char seg; void *sof; } structfuncaddress; it is thus possible to define: structfuncaddress funcaddress; and to assign a function address on 24 bits by using: funcaddress = addressof( foo ); where addressof() is defined by #define addressof(f) \ (structfuncaddress) { seg(f), sof(f) } and to make the function call do: farcall (funcaddress); where farcall is defined by #define farcall(f) \ asm(ocalls (%0),(%1)o: : oro(f.seg),oro(f .sof)) the possibility of using the seg(x) and sof(x) is restricted to the program execution. for ex- ample it is not possible to define a table of functions like: const structfuncaddresstab_func[] = {
43/98 second example: the st92r195 { seg(func0), func0}, { seg(func1), func1}, }; because seg(func0) is not resolved, it is translated to asm(oseg func0o); which is not ac- cepted by the c compiler. to avoid this limitation, such a table could be defined in assembly by; .data .byte seg func0 .byte func0 .byte seg func1 .byte func1 to avoid having to define all tables of functions in assembly, a possible implementation will now be proposed. this solution is based on the use of an automaton taken from the example. for a normal application (no far function) one can define: void (*const tab_func[])(void) = { { func0}, { func1}, }; then the function call is done by: void (*pf)(void); pf = tab_func[0]; pf(); on v4.2, with a far function, a clean way of doing this would be: const enum action = {id_func0, id_func1};
44/98 second example: the st92r195 const action tab_func[] = { { id_func0}, { id_func1}, }; action pf; pf = tab_fun[0]; select_action(pf); void select_action(action x) { switch (x) { case id_func0: func0(); break; case id_func1: func1(); break; } } thus instead of doing the call by the function pointer, it is done by the switch. note that this method can be automated using the pre-processor. the pre-processor can help generate the enum and the switch table automatically. the idea is to create a single file which can be viewed as a ounique c declaration data baseo. this is a very clean and portable method. the following is a description of this method. for example it is possible to define the table in a separate file called tab.rtl: def ( func0 ) def ( func1 ) where def is a macro that will be redefined at pre-processor level as necessary. note that more attributes can be associated to a given function, using a macro definition with more pa- rameters. then in a file (here pointer.c) where the array needs to be used : #undef def #define def(a) id_ ## a, <= redefi ne def to generate the enum enum action { #include otab.rtlo
45/98 second example: the st92r195 }; #undef def #define def(a) { id_ ## a }, <= redefine def to generate the array const enum action tab_func[] = { #include otab.rtlo }; #undef def #define def(a) {void a(void)), <= redefine def to generate prototypes #include otab.rtlo void select_action(enumaction); void main(void) { enum action pf; pf = tab_func[0]; <= select the function to execute select_action(pf); } void select_action(enumaction x) { switch (x) <= treat the function to execute according { to array. #undef def #define def(a) case id_ ## a: a(); break; #include otab.rtlo default: fatal(); } } void func0(void) {return;} void func1(void) {return;} the code generated by the c pre-processor is: # 1 opointer.co enum action { # 1 otab.rtlo 1
46/98 second example: the st92r195 id_func0, id_func1, # 5 opointer.co 2 }; const enum action tab_func[] = { # 1 otab.rtlo 1 { id_func0 }, { id_func1 }, # 12 opointer.co 2 }; void func0(void); void func1(void); void select_action(enumaction); void main(void) { enum action pf; pf = tab_func[0]; select_action(pf); } void select_action(enumaction x) { switch (x) { # 1 otab.rtlo 1 case id_func0: func0(); break; case id_func1: func1(); break; # 32 opointer.co 2 default: fatal(); } } void func0(void) {return;} void func1(void) {return;} of course, this can be applied to a more complete table containing several elements, not just the pointer.
47/98 second example: the st92r195 5.4 managing data there is no automatic management of dprs in the v4.2 compiler. the dpr positioning is left up to the user. taking the example of the st92r195 we have: dpr3 can be fixed to point to the ram page (page 83h) for stack and variable accesses in ram dpr2 can be fixed to point to the tdsram page (page 8ah) for osd and teletext variables dpr0 and dpr1 are free for managing the constants in various pages of rom dpr3 and dpr2 will never be modified during program execution. thus, the initialization of their value will only be done once. for dpr0 and dpr1 two solutions are possible: group dpr0-1 and have access to two contiguous 16 kbyte pages this case is advantageous because the granularity of the memory is 32k, and data transfers are supposed to be done from rom to ram or tdsram only. use dpr0 and dpr1 separately in this case, it will be necessary to map all the constants by blocks of 16 kbytes only. the advantage is you can scan a graph in rom for example, and access data in rom in another segment, at the same time. the second case is not recommended for the st92r195, because it makes using the dprs more difficult and may generate software errors. it would limit the maximum data size to 16 kbytes. code maintainability may also be more difficult. in the st92r195, memory usage is as follows: ram: less than 16 kbytes (512bytes)., thus only one dpr can be used, it is fixed. tdsram: less than 16 kbytes (8 kbytes), thus only one dpr can be used, it is fixed. rom more than 64 kbytes will be used, two dprs are left free for the rom, their contents can be modified depending on the rom accessing requirements. note also that transfers should occur only either from rom to ram, from rom to tdsram, or in either direction between ram and tdsram. the proposed scheme is to group dpr0 and dpr1. thus, the granularity will be 32 kbytes for the data. then, all data transfer (as described above) can be easily implemented just by mod- ifying the dpr0 and dpr1 as needed. this scheme will be implemented in the example. the application example presented here shows access to data located in 4 different seg- ments, 0, 1, 2 and 3.
48/98 second example: the st92r195 it uses a 256 kbyte external rom, and the on-chip ram and tdsram. the mapping used is as follows: internal memory external memory ram no memory no memory rom data no memory tdsram no memory rom code rom data rom data & code rom data rom data rom code segment 0 segment 1 segment 2 segment 3 segment 20 segment 22 dpr1 = 05 dpr0 = 04 dpr1 = 01 dpr0 = 00 dpr1 = 03 dpr0 = 02 dpr1 = 07 dpr0 = 06 dpr1 = 09 dpr0 = 08 dpr1 = 0bh dpr0 = 0ah dpr1 = 0dh dpr0 = 0ch dpr1 = 0fh dpr0 = 0eh dpr3 = 83h dpr2 = 8ah
49/98 second example: the st92r195 5.4.1 c and assembly directives for managing the data the assembler provides directives for accessing the page and offset of a specific data. for example, if var is located at address 0x20ff00 then: ld dpr0, #pag var ld r2, #pof var <= #pof var is a 14-bit address. will load dpr0 with 0x83 (page 3 of segment 0x20) and r2 with the contents of var from ad- dress 0x20ff00. the same thing is available in c, but using macros that refer to the pag & pof of the assem- bler. this is: pag(var); pof(var); the result will be the same. it must be understood that arrays of constants cannot be defined in c with these macros. in the same way as for functions, they can be defined in assembly. note also that if relocation is used, the pof macro is unnecessary because the offset of the relocated variable will always correspond to the correct dpr access. 5.4.2 managing the data pointer changes the ideal would to minimize the dpr modifications. a very clean way of programming with the constraint of the dprs would be, for functions that need to call far variables, to pass the dpr contents as a parameter of the function itself. for example: typedef struct fardata { unsigned char dpr; unsigned char *var; <= or even better: void * var; }; unsigned char string1[] = othis is an example of constant datao; void main() { fardata var1 ; ... var1.dpr = pag(string1); var1.var = string1; function_x(var1) ... }
50/98 second example: the st92r195 void function_x(fardatafar_var) { spp(mmu_pg); <= set page 21 for mmu register page dpr0_p = (far_var.dpr) & 0xfe; <= get dpr0 value dpr1_p = dpr0_p + 1; <= set dpr1 depending on dpr0 value ... normal access to far_var variable which is now covered by the dprs ... } dpr0 is anded with 0xfe in order to take the even value of the page, dpr0 having always even values and dpr1 odd ones. in this example the function function_x will be able to access data located in any page. this is what is implemented in the file display.c. in the example, the menu is split into dif- ferent files, and these files are mapped in various blocks. this implementation allows you to map the constants without having to worry where they are mapped. refer to it for a detailed example. note : this is feasible only because of the chosen memory mapping. the rom is always ac- cessed using dpr0 & dpr1 grouped together to form contiguous 32 kbytes blocks. the ram and the tdsram are always accessible through dpr3 and dpr2, which are fixed. looking at the first application example, the modifications are the following (in bold charac- ters): in routine display_string: unsigned char * display_string(unsignedchar *pointer, fardata string_pointer ) { save_page; /* store the page register */ spp(mmu_pg); /* set the mmu page (21) */ save_dpr; /* save the old dpr0 & 1 */ dpr0_p = string_pointer.dpr & 0xfe; /* set dpr0 to the struct dpr value */ dpr1_p = dpr0_p + 1; /* set dpr1 contiguous to dpr0 */ while (*string_pointer.var != '\0') pointer = write_character(pointer, *string_pointer.var++); restore_dpr; /* restore the dpr0 & 1 */ restore_page; /* restore the register page */ return pointer; /* return the incremented address */ }
51/98 second example: the st92r195 in routine show_menu: void show_menu() { unsigned char *j; fardata x; clear_dram_row(10); /* clear osd rows */ clear_dram_row(11); clear_dram_row(12); j = get_dram_address(display_characters,r ow_10); j=j+10; x.var = (unsigned char *) st92195_string; /* init. the fardata struct */ x.dpr = pag(st92195_string); display_string(j, x); /* copy the string in tdsram */ 5.4.3 data page registers and port data registers in the example the data page registers are located in page 21 of the paged registers (group f). the port data registers are thus located as on st9, in the system register group, and are always accessible without having to set a page. in a structured st9 application, the page is modified only when accessing peripherals. this al- lows you to have an application based on: high level software routines: main algorithms, independent of peripherals (either internal or external hardware). low level software routines: routines for peripherals and hardware management. in the st9, the high level routines do not modify the peripherals, they thus never modify the page pointer (r234) in system register group. the low level routines can then modify the page pointer without having to fear a loss of context in the high level routines. in the st9+, if the dprs are mapped in page 21, the page pointer will be modified by the high level routines. thus, the low level routines that modify the register page will now have to save the page pointer before modifying it and then restore it before exiting the routine.
52/98 second example: the st92r195 5.5 mapping the application with the scriptfile the scriptfile used for the example is the following: output_format(oa .out-st9o) output_arch(st9) input(crt9.o const.o main.o display.o code04.o code08.o automat.o) memory { /* define your memory mapping */ code00 : origin = 0x000000, length = 64k, mmu = no no no no data_code04 : origin = 0x010000, length = 32k, mmu = dpr0 dpr1 data06 : origin = 0x018000, length = 32k, mmu = dpr0 dpr1 code08 : origin = 0x020000, length = 32k, mmu = dpr0 dpr1 data0a : origin = 0x028000, length = 32k, mmu = dpr0 dpr1 data0c : origin = 0x030000, length = 32k, mmu = dpr0 dpr1 data0e : origin = 0x038000, length = 32k, mmu = dpr0 dpr1 ram : origin = 0x20ff00, length = 256 tdsram : origin = 0x228000, length = 8k } sections { _stack_size = defined(_stack_size) ? _stack_size : 40; _user_stack_size = defined(_user_stack_siz e)? _user_stack_size : 40; .text : { _text_start = .; crt9.o(.text) display.o(.text) main.o(.text) _etext = .; do_option_i; _text_end = .; } >code00 dat_cd04.bk9 :{ const.o(.data) code04.o(.text) automat.o(.text) automat.o(.data) } > data_code04 data06.bk9 :{ } > data06
53/98 second example: the st92r195 code08.bk9 :{ code08.o(.text) *(.text) } > code08 data0a.bk9 :{ menu1.o(.data) } > data0a data0c.bk9 :{ menu2.o(.data) } > data0c data0e.bk9 :{ menu3.o(.data) } > data0e .data :{ _data_start = .; *(.data) _data_end = .; }>ram .bss : { _bss_start = .; *(.bss common) _ebss =.; _bss_end = .; _stack_start = defined(_stack_start)? _stack_start : .; _stack_end = _stack_start + _stack_size; _user_stack_start = defined(_user_stack_start)? _user_stack_start : _stack_end; _user_stack_end = _user_stack_start + _user_stack_size; }>ram } note that if you want to use a 64 kbyte block instead of 32 kbyte blocks, it will only be possible to map code (not data) in these blocks. the maximum data block granularity being 32 kbytes.
54/98 second example: the st92r195 5.6 libraries the v4.2 version of the compiler provides a complete set of libraries, depending on the dif- ferent compilation and link options. it is very important to select the correct libraries that will be linked with the application. refer to the v4.2 release note for the various libraries available. in the example, the libraries used were: stdr9f.l libr9f.l what must be understood is that because the far memory model is chosen, the libraries will also have to be far, that is, called with calls and returned with rets . it is also important to note that the objects extracted from the libraries will be placed by the linker at the very end of the .text section. to be precise, they are placed in the segment that contains the *(.text) in the scriptfile. the libraries also contain some initialized variables (.data). these variables need to be mapped correctly in the scriptfile. 5.7 the compiler and linker options for the compiler the options are: -mfar : for far function memory model -mlink : for st9+ new instructions -g : get debug options -o : set the optimizer on -tr9 : use tr9 during compilation chain -fomit-frame-pointer : avoid frame pointer when not needed -wall : get all possible warnings -wa,-ahld : get a listing file for the linker the options are: -m : generate a map file -t : use a scriptfile -i : get copy of init variables at startup -mmu : allow relocation and far memory model
55/98 second example: the st92r195 5.8 application files the necessary application files: makefile the file needed to make the application makedep the dependency description file main.c contains the main routine const.c contains some constants definition automat.c contains the various automaton routines menu1.c contains one menu line (constant string) menu2.c contains one menu line (constant string) menu3.c contains one menu line (constant string) code04.c contains some routines of the automaton code08.c contains some routines of the automaton display.c contains the osd routines crt9.asm the startup file, contains the interrupt vectors, and calls main it also initializes the st9+ correctly st92r195.scr the scriptfile, contains the memory mapping description st92r195.u the executable needed by the debugger st92r195.hex the hexadecimal file needed to program eprom/otps in addition, all header files and some st9 macros are used and defined in: st9macro, display.h, newreg.h, mmu.h, define.h and osd_const.h. 5.9 the debugger configuration file the scriptfile will generate the *.bk9 files. these files correspond to the various segments to be loaded by the debugger. a file name st92r195.bl9 was also created by the linker. it con- tains the loading order of each *.bk9 file needed by the debugger. to force the load of the seg- ments when loading the application with the debugger, a file needs to be created with the same name as the executable (here st92r195.u), with extension .gdb. this file must contain: source st92r195.bl9 the debugger will first load the hardware.gdb file then the st92r195.u and finally the st92r195.gdb.
56/98 appendix - source files 6 appendix - source files 6.1 common source files 6.1.1 define.h /*************** ********************************************************* define.h header file ================ this file contains: - the declaration of the automaton type - several definitions ---------------- ----------- author: thierr y crespo company: stmicroelectronics version: v1.0 date: 25/02/97 ---------------- ------------ **************** *******************************************************/ #define on 1 #define off 0 #define false 0 #define true 1 #define up 0x01 #define down 0x02 #define escape 0x04 #define set_menu 0x05 #define bit0 0x01 #define bit1 0x02 #define bit2 0x04 #define red 0x1f #define blue 0x4f #define orange 0x02 #define green 0x2f #define max_states 20 typedef struct automaton { unsigned char state; unsigned char event;
57/98 appendix - source files unsigned char action; unsigned char next_state; } automaton; typedef struct fdata{ unsigned char dpr; unsigned char *var; } fardata; 6.1.2 mmu.h /*************** *********************************************************/ /* st9+ family mmu control registers release 1.0 */ /* st9+ family mmu control register */ /* */ /*************** *********************************************************/ /*************** *************************/ /* mmu control registers definition */ /*************** *************************/ #define mmu_pg ((unsigned char)21) /* mmu control registers page */ register unsigned char dpr0 asm(or224o); register unsigned char dpr1 asm(or225o); register unsigned char dpr2 asm(or226o); register unsigned char dpr3 asm(or227o); /* mmu data page registers located in the page 21 */ register unsigned char dpr0_p asm(or240o); register unsigned char dpr1_p asm(or241o); register unsigned char dpr2_p asm(or242o); register unsigned char dpr3_p asm(or243o); register unsigned int dpr01_p asm(orr240o); register unsigned int dpr23_p asm(orr242o); /* mmu code segment register */ register unsigned char csr asm(or244o); /* mmu interrup t segment register */ register unsigned char isr asm(or248o); /* mmu dma segment register */
58/98 appendix - source files register unsigned char dmasr asm(or249o); /* mmu configur ation registers */ register unsigned char emr1 asm(or245o); #define emr1_mc ((unsigned char)0x40) /* mode control */ #define emr1_ds2n ((unsigned char)0x20) /* data strobe 2 enable */ #define emr1_asaf ((unsigned char)0x10) /* address strobe as alternate function */ #define emr1_nmb ((unsigned char)0x08) /* no multiplexed bus */ #define emr1_eto ((unsigned char)0x04) /* external toggle */ #define emr1_bsz ((unsigned char)0x02) /* bus size */ #define emr1_romless ((unsigned char)0x01) /* romless */ register unsigned char emr2 asm(or246o); #define emr2_bromless ((unsigned char)0x80) /* boot-roml ess */ #define emr2_encsr ((unsigned char)0x40) /* enable code segment register */ #define emr2_dprrem ((unsigned char)0x20) /* data page register reapped */ #define emr2_memsel ((unsigned char)0x10) /* memory select */ #define emr2_pas ((unsigned char)0x0c) /* program memory address strobe stretch */ #define emr2_das ((unsigned char)0x03) /* data memory address strobe stretch */ #define set_dpr_system emr2 |= emr2_dprrem #define seg(f) ({ \ unsigned char __seg; \ asm(old %0, #seg %1o : o=ro(__seg) : omo(f) ); \ __seg; \ }) #define sof(f) ({ \ void *__sof; \ asm(oldw %0, #sof %1o : o=ro(__sof) : omo(f) ); \ __sof; \ }) #define pag(f) ({ \ unsigned char __pag; \
59/98 appendix - source files asm(old %0, #pag %1o : o=ro(__pag) : omo(f) ); \ __pag; \ }) #define pof(f) ({ \ void *__pof; \ asm(oldw %0, #pof %1o : o=ro(__pof) : omo(f) ); \ __pof; \ }) /* inter-segment function call through a 3 byte pointer: structfuncaddress x; ... x = addressof (func); ... farcall (x); */ /* 3 byte structure hosting a far function pointer */ typedef struct { unsigned char seg; void *sof; } structfuncaddress; /* operator creating a temporary object of type structfuncaddress */ #define addressof(f) (structfuncaddress){ seg( f), sof( f) } /* call through a structfuncaddress pointer */ #define farcall(f) asm(ocalls (%0),(%1)o : : oro(f.seg), oro(f.sof)) #define farcallpointer(f) farcall(f)
60/98 appendix - source files 6.1.3 st9macro.h /*************** ********************************************************* st9macro.h header file ====================== this file contains macros used in the c ---------------- ----------- author: thierr y crespo company: stmicroelectronics version: v1.0 date: 25/02/97 ---------------- ------------ **************** *******************************************************/ /*************** **********************/ /* c macros for inline assembly code */ /*************** **********************/ #define halt() asm(ohalto); /* halt instruction */ #define spm() asm(ospmo); /* set program memory */ #define sdm() asm(osdmo); /* set data memory */ #define ei() asm(oeio); /* enable interrupts*/ #define di() asm(odio); /* disable interrupts*/ #define nop asm (onopo); /* 6 cycle clock tempo */ #define save_page asm(opushu r234o); #define restore_page asm(opopu r234o); /*************** ****************************************/ /* c macros for inline assembly code with an operand */ /*************** ****************************************/ /* set page pointer to value page */ #define spp(page) asm(ospp %0o:: oio (page)); /* set working register pointer to value bank */ #define srp(bank) asm(osrp %0o:: oio (bank)); /* load a value to a working register */ #define ldw_rr_xx(reg,value) asm(oldw rr%q0,%1o:: oio (reg) ,orro (value));
61/98 appendix - source files #define restore_dpr asm(opopw rr240o); #define save_dpr asm(opushw rr240o); 6.1.4 display.h /*************** ********stmicroelectronics ************************ filename : display.h version : v0.0 date : february 20, 1997 author(s) : thierry crespo processor : st92195 description : this module contains constant definitions and function prototypes. modifications: - - - **************** ************************************************************ */ unsigned char *write_character(unsigned char *, unsigned char); const unsigned char *write_mbt_buffer(constunsigned char *); void init_display(void); void enable_display(unsignedchar); void disable_display(unsigned char); unsigned char *get_dram_address(unsignedchar, unsigned char); void show_menu(); void clear_menu(); #define display_characters 0x00 #define display_attributes 0xff #define row_all 0xff #define row_1 1 #define row_2 2 #define row_3 3 #define row_4 4 #define row_5 5 #define row_6 6 #define row_7 7 #define row_8 8 #define row_9 9 #define row_10 10 #define row_11 11 #define row_12 12 #define row_13 13
62/98 appendix - source files #define row_14 14 #define row_15 15 #define row_16 16 #define row_17 17 #define row_18 18 #define row_19 19 #define row_20 20 #define row_21 21 #define row_22 22 #define row_23 23 #define flash 0x08 #define steady 0x09 #define horizontal_delay 0x30 #define horizontal_position 0x70 #define vertical_position0x0e 6.2 the first application example source files : the st92195 6.2.1 main.c /*************** ********stmicroelectronics ************************ filename : main.c version : v1.0 date : february 20, 1997 author(s) : thierry crespo processor : st92195 description : this file contains: - the main routine - the wait_for_event routine the purpose of the main is to do an infini te loop waiting for events and to treat the received events depending on the automaton. modifications: **************** *******************************************************/ #include odefine.ho #include odisplay.ho #include ost9macro.ho #include char wait_for_event();
63/98 appendix - source files void wait_for_second(unsigned char); automaton run_automaton(automaton); /*************** ********************************************************* variable definitions **************** ********************************************************/ extern const struct automaton automaton_table[9]; char init_var []=o this is an initialized variable o; automaton osd_menu; /*************** ************************************************** void main(void) object: contai ns the main routine. it initializes the variab les, waits for an input event, when an input event is received, it scans the automaton table, then modifies the state of tit calls the automaton and does the loop forever. input: none output: none **************** *************************************************/ void main() { init_display(); osd_menu.state = off; /* initialization of the automaton */ osd_menu.event = set_menu; /* set first event to show the menu */ osd_menu = run_automaton(osd_menu); /* perform initialization of menu */ while(1) { osd_menu.event = wait_for_event(); /* wait for an input event */ /* return the event */ osd_menu = run_automaton(osd_menu); /* perform automaton depending on */ /* event received */ } } /*************** ************************************************** automaton run_au tomaton(automatonmenu) object: this routine scan the automaton depending on the
64/98 appendix - source files state and event of the current automaton. it return s the updated automaton. input: automat on output: automa ton => updated automaton **************** *************************************************/ automaton run_au tomaton(automatonmenu) { unsigned char count; count = 0; /* counter to scan au- tomaton table */ while(1) /* scan the automaton table to */ { /* find the corresponding one */ if (( menu.state == automaton_table[count].state) && ( menu.event == automaton_table[count] .event)){ /* get the state and event */ /* udate the automaton */ /* perform the action */ menu.actio n = (void *) automaton_table[count].action; menu.state = automaton_table[count].next_state; menu.actio n(); return (menu); } else count++; if (count >= max_states) return(menu); /* if table overflow */ } return(menu); } /*************** ************************************************** char wait_for_even t(void) object: the routine selects a random char value, if this value corresponds to a event (01, 02, 04) then it returns the event number. it loops until a event is found input: none output: event => a char, the event
65/98 appendix - source files events can be: up down escape set_menu **************** *************************************************/ char wait_for_event() { char event; while(1) { event = (char) rand(); /* get a random char */ switch (event) { case up: { wait_for_second(4); return(up); /* return event is same */ } case down: { wait_for_second(4); return(down); } case escape: { wait_for_second(4); return(escape); } case set_menu: return(set_menu); default:bre ak; } } } /*************** ******************************************** void wait_for_second(unsigned char number) this routine does a tempo input: number => approximate number of seconds to wait ouput: none **************** ********************************************/
66/98 appendix - source files void wait_for_second(unsigned char number) { unsigned int i; while (number != 0) { for (i=0xfff2; i!=0; i--) { asm(onopo); asm(onopo); asm(onopo); asm(onopo); asm(onopo); } number--; } } 6.2.2 actions.c /*************** ********************************************************* action.c source file ==================== this file contains all the functions implementing the actions of the automaton. ---------------- ----------- author: thierr y crespo company: stmicroelectronics version: v1.0 date: 25/02/97 ---------------- ------------ **************** *******************************************************/ #include odefine.ho #include odisplay.ho #include ost9macro.ho void red_to_blue(); void blue_to_red(); void blue_to_green(); void green_to_blue(); void green_to_red();
67/98 appendix - source files void switch_attr(char, char); /*************** ************************************************** void switch_attr(char, char); object: set a port bit high or low input: the bort bit (char), the status (char) output: none **************** *************************************************/ void switch_attr(char color, char state) { unsigned char *j; unsigned char row_number = red; switch (color) { case red: row_number = 10; break; case blue: row_number = 11; break; case green: row_number = 12; break; default: break; } if (state == on) { j = get_dram_address(display_attributes,r ow_number); j=j+9; j = write_character(j,0xa0); } else { j = get_dram_address(display_attributes,r ow_number); j=j+9; j = write_character(j,0x80); } }
68/98 appendix - source files /*************** ************************************************** object: toggle the attr to obtain the state corresponding to the automaton table input: none output: none **************** *************************************************/ void red_to_green(){ switch_attr(green, on); switch_attr(red, off); } void red_to_blue(){ switch_attr(blue, on); switch_attr(red, off); } void blue_to_red(){ switch_attr(blue, off); switch_attr(red, on); } void blue_to_green(){ switch_attr(blue, off); switch_attr(green, on); } void green_to_blue(){ switch_attr(green, off); switch_attr(blue, on); } void green_to_red(){ switch_attr(green, off); switch_attr(red, on); } 6.2.3 const.c /*************** ********************************************************* const.c source file ================ this file contains: - the automaton table to be put in rom - the constant table for on screen display ---------------- -----------
69/98 appendix - source files author: thierr y crespo company: stmicroelectronics version: v1.0 date: 25/02/97 ---------------- ------------ **************** *******************************************************/ #include odefine.ho #include odisplay.ho extern void clear_menu(); extern void red_to_green(); extern void red_to_blue(); extern void blue_to_red(); extern void blue_to_green(); extern void green_to_blue(); extern void green_to_red(); const char constant1[]=othis is the first constanto; const char blank[]=o o; const char constant2[]=othis is the second constanto; const struct automaton automaton_table[max_states]= { {red, up, (void *) &red_to_green,green}, {red, down, (void *) &red_to_blue,blue}, {red, escape, (void *) &clear_menu,off}, {off, set_menu, (void *) &show_menu,red}, {blue, up, (void *) &blue_to_red,red}, {blue, down, (void *) &blue_to_green,green}, {blue, escape , (void *) &clear_menu,off}, {green, up, (void *) &green_to_blue,blue}, {green, down, (void *) &green_to_red,red}, {green, escape, (void *) &clear_menu,off}, }; const unsigned char st92195_string[] = ost92195 application noteo; const unsigned char thomson_string[] = o stmicroelectron ics o; const unsigned char demo_string[] = o demo o;
70/98 appendix - source files 6.2.4 display.c /*************** ********stmicroelectronics ************************ filename : display.c version : v0.0 date : february 20, 1997 author(s) : thierry crespo processor : st92195 description : this file contains the source code for the on screen display driver. modifications: **************** ************************************************************ */ #include odefine.ho #include odisplay.ho #include onewreg.ho #include ost9macro.ho #include oosd_cons.ho / **************** ************************************************************ * inputs : none outputs : st9 osd registers description: this function initializes the display cell for both tv mode (menu, stats...) and teletext mode. **************** ************************************************************ */ void init_display(void) { unsigned int i; spp(sccr_pg); /* select synchro controller page */ csyct = 0x00; /* select vsync and hsync from vsync and hsync inputs (not from cvbs) */ /* select hsync and vsync polarity as well as the phase delay */ /*between hsync and vsync which is chassis hardware dependant */ csysu = 0xc4; spp(tccr_pg); skccr = 0x0a; for (i=0x1fff ; i!=0 ; i--); skccr = 0x8a;
71/98 appendix - source files for (i=0x1fff ; i!=0 ; i--); pxccr = 0x80; slccr = 0x80; spp(tdsramc2_pg); config = 0x07; spp(dcr1_pg); hblank = horizon tal_delay; hpos = horizont al_position; vpos = vertical _position; fsc = 0xaf; hsc = 0x3f; /* header,status 1,2 enable */ ncs = 0x07; chpos = 0x99; cvpos = 0x00; scl = 0x00; /* scrolling disable */ sch = 0x2f; dcm0r = 0x84; /* display en,semitransparent en,fringe en,conceal en,global fringe en,global rounding en,screen format,single/double*/ dcm1r = 0x0d; tdsraml = 0x80; hsc = 0x0; de0 = 0x0; de1 = 0x0; de2 = 0x0; spp(dcr2_pg); dc = 0x7f; } / **************** ************************************************************ * inputs : row number to display outputs : st9 osd registers description: this function displays a row. **************** ************************************************************ */ void enable_display(unsignedchar row_number) { unsigned char i, j; /* temporary storage */ /* set bit position depending on the row number */ for (i=1, j=row_number; j>1; j--)
72/98 appendix - source files asm (orol %0o : :oro(i)); /* enable selected row */ spp(dcr1_pg); if (row_number == row_all) { de0 = 0xff; de1 = 0xff; de2 = 0xff; return; } if (row_number <= row_8) { de0 = de0 | i; return; } if (row_number <= row_16) { de1 = de1 | i; return; } if (row_number <= row_23) { de2 = de2 | i; } } / **************** ************************************************************ * inputs : row number to display outputs : st9 osd registers description: this function displays a row. **************** ************************************************************ */ void disable_display(unsigned char row_number) { unsigned char i, j; /* temporary storage */ /* set bit position depending on the row number */ for (i=1, j=row_number; j>1; j--) asm (orol %0o : :oro(i)); /* disable selected row */ spp(dcr1_pg); if (row_number == row_all)
73/98 appendix - source files { de0 = 0x00; de1 = 0x00; de2 = 0x00; return; } if (row_number <= row_8) { de0 = de0 & ~i; return; } if (row_number <= row_16) { de1 = de1 & ~i; return; } if (row_number <= row_23) { de2 = de2 & ~i; } } / **************** ************************************************************ * inputs : row number outputs : dram position description: this function returns the dram location to start with according to the row number. **************** ************************************************************ */ unsigned char *get_dram_address(unsignedchar selection, unsigned char row_position) { if (selection == display_characters) return (unsigned char *)(0x8000 + ((row_posi tion - 1) * 40)); else return (unsigned char *)(0x8400 + ((row_posi tion - 1) * 40)); } / **************** ************************************************************ * inputs : charac ter chain pointer outputs : character chain pointer description: this function copies the character chain into the
74/98 appendix - source files multi byte transfer buffer. **************** ************************************************************ */ const unsigned char *write_mbt_buffer(constunsigned char *cha_pointer) { unsigned char i; spp(tdsramc0_pg ); asm volatile (o ld %0,#0xf0 repeat1: ld (%0)+,%1+ cp %0,#0 jxnz repeat1 o :o=ro(i) :omo(*cha_pointer)); spp(tdsramc1_pg ); asm volatile (o ld %0,#0xf0 repeat2: ld (%0)+,%1+ cp %0,#0 jxnz repeat2 o :o=ro(i) :omo(*cha_pointer)); spp(tdsramc2_pg ); asm volatile (o ld %0,#0xf0 repeat3: ld (%0)+,%1+ cp %0,#0xf8 jxnz repeat3 o :o=ro(i) :omo(*cha_pointer)); bufc = 0x01; asm(o nop nop o); while(bufc & 0x01) asm(onopo); return cha_pointer; } / **************** ************************************************************ * inputs : dram pointer - point the location to start with character to write into the dram outputs : return the next dram location description: this function writes the given character. **************** ************************************************************ */ unsigned char *write_character(unsigned char *pointer, unsigned char character) { *pointer++ = character; return pointer;
75/98 appendix - source files } / **************** ************************************************************ * inputs : .dram pointer - point the location to start with character to write into the dram .character .number outputs : return the next dram location description: this function writes the given character. **************** ************************************************************ */ unsigned char *write_character_n(unsignedchar *pointer,unsigned char character ,unsigned char number) { while(number!=0) { pointer = write_character(pointer,chara cter); number--; } return pointer; } / **************** ************************************************************ * inputs : dram pointer - point the location to start with string pointer - point the first character to write into the dram outputs : return the next dram location see write_character description: this function writes the given string. **************** ************************************************************ */ unsigned char * display_string(unsignedchar *pointer, const unsigned char *string_pointer) { /* warning - do not modify working registers */ while (*string_pointer != '\0') pointer = write_character(pointer, *string_pointer++); return pointer; } / **************** ************************************************************ * inputs : none
76/98 appendix - source files outputs : none description: this function clear a tdsram row in character area **************** ************************************************************ */ void clear_dram_row(unsignedchar row_number) { unsigned char i; unsigned char *j; j = get_dram_address(display_characters,r ow_number); for (i=40; i!=0; i--) { j = write_character(j,0x00); } j = get_dram_address(display_attributes,r ow_number); for (i=40; i!=0; i--) { j = write_character(j,0x20); } } / **************** ************************************************************ * inputs : none outputs : none description: this function displays a simple menu **************** ************************************************************ */ void show_menu() { unsigned char *j; unsigned char *i; clear_dram_row(10); clear_dram_row(11); clear_dram_row(12); j = get_dram_address(display_characters,r ow_10); j=j+10; i = (unsigned char *) st92195_string; display_string(j, i); j = get_dram_address(display_attributes,r ow_10); j=j+8; j = write_character(j,red); j = write_character(j,0xa0);
77/98 appendix - source files j = write_character_n(j,red,24); j = write_character(j,0x80); j = get_dram_address(display_characters,r ow_11); j=j+10; i = (unsigned char *) thomson_string; display_string(j, i); j = get_dram_address(display_attributes,r ow_11); j=j+8; j = write_character(j,blue); j = write_character(j,0x80); j = write_character_n(j,blue,24); j = write_character(j,0x80); j = get_dram_address(display_characters,r ow_12); j=j+10; i = (unsigned char *) demo_string; display_string(j, i); j = get_dram_address(display_attributes,r ow_12); j=j+8; j = write_character(j,green); j = write_character(j,0x80); j = write_character_n(j,green,24); j = write_character(j,0x80); enable_display(row_10); enable_display(row_11); enable_display(row_12); } / **************** ************************************************************ * inputs : none outputs : none description: this function displays a simple menu **************** ************************************************************ */ void clear_menu(void) { disable_display(row_10); disable_display(row_11); disable_display(row_12); }
78/98 appendix - source files 6.3 the second application example source files : the st92r195 6.3.1 main.c /*************** ********stmicroelectronics ************************ filename : main.c version : v1.0 date : february 20, 1997 author(s) : thierry crespo processor : st92r195 description : this file contains: - the main routine - the wait_for_event routine the purpose of the main is to do an infini te loop waiting for events and to treat the received events depending on the automaton. modifications: - **************** ************************************************************ */ #include ommu.ho #include odefine.ho #include odisplay.ho #include ost9macro.ho #include static char wait_for_event(); static void wait_for_second(unsignedchar); extern automaton run_automaton(automaton); /*************** ********************************************************* variable definitions **************** ********************************************************/ extern const struct automaton automaton_table[9]; char init_var []=o this is an initialized variable o; automaton osd_menu; / **************** ************************************************************ * function : void main(void)
79/98 appendix - source files inputs : none outputs : none description: contains the main routine. it initializes the varia- bles, waits for an input event, when an input event is received, it scans the automaton table, then modifies the state of tit calls the automaton and does the loop forever. **************** *************************************************/ void main() { init_display(); osd_menu.state = off; /* initialization of the automaton */ osd_menu.event = set_menu; /* set first event to show the menu */ osd_menu = run_automaton(osd_menu); /* perform initialization of menu */ while(1) { osd_menu.event = wait_for_event(); /* wait for an input event */ /* return the event */ osd_menu = run_automaton(osd_menu); /* perform automaton depending on */ /* event received */ } } /*************** ************************************************** function : static char wait_for_event(void) inputs : row number to display outputs : event description: the routine selects a random char value, if this value correspond s to a event (01, 02, 04, 05 ...) then it return s the event number. it loops until a event is found and does a small tempo for visual effect. events can be: up down escape
80/98 appendix - source files set_menu **************** *************************************************/ static char wait_for_event() { unsigned char event; while(1) { event = (char) rand() % 6; /* get a random char */ switch (event) { case up: { wait_for_second(4); return(up); /* return event is same */ } case down: { wait_for_second(4); return(down); } case escape: { wait_for_second(4); return(escape); } case set_menu: return(set_menu); default:bre ak; } } } / **************** ************************************************************ * function : static void wait_for_second(unsigned char number) inputs : number => approximate number of seconds to wait outputs : none description: this routine does a tempo **************** ********************************************/ static void wait_for_second(unsigned char number) { unsigned int i; while (number != 0) {
81/98 appendix - source files for (i=0xfff2; i!=0; i--) { asm(onopo); asm(onopo); asm(onopo); asm(onopo); asm(onopo); } number--; } } 6.3.2 display.c /*************** ********stmicroelectronics ************************ filename : display.c version : v1.0 date : february 20, 1997 author(s) : thierry crespo processor : st92r195 description : this file contains the source code for the on screen display driver. modifications: - - - **************** ************************************************************ */ #include odefine.ho #include odisplay.ho #include onewreg.ho #include ost9macro.ho #include oosd_cons.ho #include ommu.ho / **************** ************************************************************ * inputs : none outputs : st9 osd registers description: this function initializes the display cell for both tv mode (menu, stats...) and teletext mode. **************** ************************************************************ */ void init_display(void)
82/98 appendix - source files { unsigned int i; spp(sccr_pg); /* select synchro controller page */ csyct = 0x00; /* select vsync and hsync from vsync and hsync inputs (not from cvbs) */ /* select hsync and vsync polarity as well as the phase delay between */ /* hsync and vsync which is chassis hardware dependant */ csysu = 0xc4; spp(tccr_pg); skccr = 0x0a; for (i=0x1fff ; i!=0 ; i--); skccr = 0x8a; for (i=0x1fff ; i!=0 ; i--); pxccr = 0x80; slccr = 0x80; spp(tdsramc2_pg); config = 0x03; spp(dcr1_pg); hblank = horizon tal_delay; hpos = horizont al_position; vpos = vertical _position; fsc = 0xaf; hsc = 0x3f; /* header,status 1,2 enable */ ncs = 0x07; chpos = 0x99; cvpos = 0x00; scl = 0x00; /* scrolling disable */ sch = 0x2f; dcm0r = 0x84; /* display en,semitrans parent en,fringe en,con- ceal en, */ /* global fringe en,global rounding en,screen format,single/double */ dcm1r = 0x0d; tdsraml = 0x80; hsc = 0x0; de0 = 0x0; de1 = 0x0; de2 = 0x0;
83/98 appendix - source files spp(dcr2_pg); dc = 0x7f; } / **************** ************************************************************ * inputs : row number to display outputs : st9 osd registers description: this function enables the display of a row. **************** ************************************************************ */ void enable_display(unsignedchar row_number) { unsigned char i, j; /* temporary storage */ save_page; /* save the register page */ /* set bit position depending on the row number */ for (i=1, j=row_number; j>1; j--) asm (orol %0o : :oro(i)); /* enable selected row */ spp(dcr1_pg); if (row_number == row_all) { de0 = 0xff; de1 = 0xff; de2 = 0xff; restore_page; /* restore the register page */ return; } if (row_number <= row_8) { de0 = de0 | i; restore_page; /* restore the register page */ return; } if (row_number <= row_16) { de1 = de1 | i; restore_page; /* restore the register page */ return; } if (row_number <= row_23) {
84/98 appendix - source files de2 = de2 | i; } restore_page; /* restore the register page */ } / **************** ************************************************************ * inputs : row number to display outputs : st9 osd registers description: this function disable the display of a row. **************** ************************************************************ */ void disable_display(unsigned char row_number) { unsigned char i, j; /* temporary storage */ save_page; /* save the register page */ /* set bit position depending on the row number */ for (i=1, j=row_number; j>1; j--) asm (orol %0o : :oro(i)); /* disable selected row */ spp(dcr1_pg); if (row_number == row_all) { de0 = 0x00; de1 = 0x00; de2 = 0x00; restore_page; /* restore the register page */ return; } if (row_number <= row_8) { de0 = de0 & ~i; restore_page; /* restore the register page */ return; } if (row_number <= row_16) { de1 = de1 & ~i; restore_page; /* restore the register page */ return; } if (row_number <= row_23)
85/98 appendix - source files { de2 = de2 & ~i; } restore_page; /* restore the register page */ } / **************** ************************************************************ * inputs : row number outputs : dram position description: this function returns the dram location to start with according to the row number. position needed for writing the osd menus. **************** ************************************************************ */ unsigned char *get_dram_address(unsignedchar selection, unsigned char row_position) { if (selection == display_characters) return (unsigned char *)(0x8000 + ((row_posi tion - 1) * 40)); else return (unsigned char *)(0x8400 + ((row_posi tion - 1) * 40)); } / **************** ************************************************************ * inputs : dram pointer - point the location to start with character to write into the dram outputs : return the next dram location description: this function writes the given character. it doesn't need any dpr management as dpr2 points always to the tdsram. **************** ************************************************************ */ unsigned char *write_character(unsigned char *pointer, unsigned char character) { *pointer++ = character; return pointer; } / **************** ************************************************************ * inputs : .dram pointer - point the location to start with character to write into the dram
86/98 appendix - source files .character .number outputs : return the next dram location description: this function writes the given character n times. it doesn't need any dpr management as dpr2 points always to the tdsram. **************** ************************************************************ */ unsigned char *write_character_n(unsignedchar *pointer,unsigned char character ,unsigned char number) { while(number!=0) { pointer = write_character(pointer,chara cter); number--; } return pointer; } / **************** ************************************************************ * inputs : dram pointer - points the location to start with string pointer - a struct to write into the dram. this is a struct containing the dpr of the data and the first character. outputs : return the next dram location see write_character description: this function writes the given string in tdsram **************** ************************************************************ */ unsigned char * display_string(unsignedchar *pointer, fardata string_pointer) { save_page; /* store the page register */ spp(mmu_pg); /* set the mmu page (21) */ save_dpr; /* save the old dpr0 & 1 */ dpr0_p = string_pointer.dpr;/* set dpr0 to the struct dpr value */ dpr1_p = dpr0_p + 1; /* set dpr1 contiguous to dpr0 */ /* warning - do not modify working registers */ while (*string_pointer.var != '\0') pointer = write_character(pointer, *string_pointer.var++); restore_dpr; /* restore the dpr0 & 1 */ restore_page; /* restor e the register page */
87/98 appendix - source files return pointer; /* return the incremented address */ } / **************** ************************************************************ * inputs : none outputs : none description: this function clears a tdsram row in character area **************** ************************************************************ */ void clear_dram_row(unsignedchar row_number) { unsigned char i; unsigned char *j; j = get_dram_address(display_characters,r ow_number); for (i=40; i!=0; i--) { j = write_character(j,0x00); } j = get_dram_address(display_attributes,r ow_number); for (i=40; i!=0; i--) { j = write_character(j,0x20); } } / **************** ************************************************************ * inputs : none outputs : none description: this function displays a simple menu made of 3 lines in row 10, 11 & 12. it uses far data. **************** ************************************************************ */ void show_menu() { unsigned char *j; fardata x; clear_dram_row(10); /* clear osd rows */ clear_dram_row(11); clear_dram_row(12);
88/98 appendix - source files j = get_dram_address(display_characters,r ow_10); j=j+10; x.var = (unsigned char *) st92195_string; /* initialize the fardata struct */ x.dpr = pag(st92195_string); display_string(j, x); /* copy the string in tdsram */ j = get_dram_address(display_attributes,r ow_10);/* set attrbutes for row 10 */ j=j+8; j = write_character(j,red); j = write_character(j,0xa0); j = write_character_n(j,red,24); j = write_character(j,0x80); j = get_dram_address(display_characters,r ow_11); j=j+10; x.var = (unsigned char *) thomson_string; x.dpr = pag(thomson_string); display_string(j, x); j = get_dram_address(display_attributes,r ow_11); j=j+8; j = write_character(j,blue); j = write_character(j,0x80); j = write_character_n(j,blue,24); j = write_character(j,0x80); j = get_dram_address(display_characters,r ow_12); j=j+10; x.var = (unsigned char *) demo_string; x.dpr = pag(demo_string); display_string(j, x); j = get_dram_address(display_attributes,r ow_12); j=j+8; j = write_character(j,green); j = write_character(j,0x80); j = write_character_n(j,green,24); j = write_character(j,0x80); enable_display(row_10); enable_display(row_11);
89/98 appendix - source files enable_display(row_12); } / **************** ************************************************************ * inputs : none outputs : none description: this function displays a simple menu **************** ************************************************************ */ void clear_menu(void) { disable_display(row_10); disable_display(row_11); disable_display(row_12); } 6.3.2 const.c /*************** ********************************************************* const.c source file ================ this file contains: - the automaton table to be put in rom - the constant table for on screen display this is only an example file. ---------------- ----------- author: thierr y crespo company: stmicroelectronics version: v1.0 date: 25/02/97 ---------------- ------------ **************** *******************************************************/ #include ommu.ho #include odefine.ho #include odisplay.ho const char constant1[]=othis is the first constanto; const char blank[]=o o; const char constant2[]=othis is the second constanto;
90/98 appendix - source files 6.3.3 menu1.c /*************** ********stmicroelectronics ************************ filename : menu1.c version : v1.0 date : february 20, 1997 author(s) : thierry crespo processor : st92r195 description : this file contains one menu line constants. it could contain up to 32kbytes of constants ; modifications: **************** ************************************************************ */ const unsigned char thomson_string[] = o stmicroelectron ics o; 6.3.4 menu2.c /*************** ********stmicroelectronics ************************ filename : menu2.c version : v1.0 date : february 20, 1997 author(s) : thierry crespo processor : st92r195 description : this file contains one menu line constants. it could contain up to 32kbytes of constants ; modifications: **************** ************************************************************ */ const unsigned char st92195_string[] = ost92195 application noteo; 6.3.6 menu3.c /*************** ********stmicroelectronics ************************ filename : menu3.c version : v1.0 date : february 20, 1997 author(s) : thierry crespo processor : st92r195 description : this file contains one menu line constants. it could contain up to 32kbytes of constants ; modifications: **************** ************************************************************ */ const unsigned char demo_string[] = o demo o;
91/98 appendix - source files 6.3.5 code04.c /******************************************************** **************** code04.c source file ==================== this file contains some functions implementing the actions of the automaton. ---------------- ----------- author: thierr y crespo company: stmicroelectronics version: v1.0 date: 25/02/97 ---------------- ------------ **************** *******************************************************/ #include odefine.ho #include odisplay.ho #include ost9macro.ho void switch_attr(char, char); void red_to_green(); / **************** ************************************************************ * inputs : color and state outputs : none description: toggle the attr to obtain the state corresponding to the automaton table **************** *************************************************/ void switch_attr(char color, char state) { unsigned char *j; unsigned char row_number = red; switch (color) { case red: row_number = 10; break; case blue: row_number = 11; break;
92/98 appendix - source files case green: row_number = 12; break; default: break; } if (state == on) { j = get_dram_address(display_attributes,r ow_number); j=j+9; j = write_character(j,0xa0); } else { j = get_dram_address(display_attributes,r ow_number); j=j+9; j = write_character(j,0x80); } } / **************** ************************************************************ * inputs : none outputs : none description: toggle the attr to obtain the state corresponding to the automaton table **************** *************************************************/ void red_to_green(){ switch_attr(green, on); switch_attr(red, off); } 6.3.8 code08.c /*************** ********************************************************* code08.c source file ==================== this file contains all the functions implementing the actions of the automaton. ---------------- -----------
93/98 appendix - source files author: thierr y crespo company: stmicroelectronics version: v1.0 date: 25/02/97 ---------------- ------------ **************** *******************************************************/ #include odefine.ho #include odisplay.ho #include ost9macro.ho void red_to_blue(); void blue_to_red(); void blue_to_green(); void green_to_blue(); void green_to_red(); extern void switch_attr(char, char); / **************** ************************************************************ * inputs : none outputs : none description: toggle the attr to obtain the state corresponding to the automaton table **************** *************************************************/ void red_to_blue(){ switch_attr(blue, on); switch_attr(red, off); } void blue_to_red(){ switch_attr(blue, off); switch_attr(red, on); } void blue_to_green(){ switch_attr(blue, off); switch_attr(green, on); } void green_to_blue(){ switch_attr(green, off); switch_attr(blue, on); } void green_to_red(){ switch_attr(green, off);
94/98 appendix - source files switch_attr(red, on); } 6.4 automat.c /*************** ********************************************************* automat.c file ================ this file contains: - the automaton routine ---------------- ----------- author: thierr y crespo company: stmicroelectronics version: v1.0 date: 25/02/97 ---------------- ------------ **************** *******************************************************/ #include ommu.ho #include odefine.ho #include odisplay.ho #include ost9macro.ho #include extern automaton run_automaton(automaton); void fatal(void); automaton run_au tomaton(automaton); void switch_action(unsignedchar); extern void blue_to_green(); extern void blue_to_red(); extern void red_to_green(); extern void red_to_blue(); extern void green_to_blue(); extern void green_to_red(); extern void clear_menu(); extern void show_menu(); extern void do_nothing(); /*************** *********************************************/ /*************** * this is the action list *** ***************/ 1
95/98 appendix - source files /*************** *********************************************/ enum action_list { id_blue_to_green , id_blue_to_red, id_red_to_green, id_red_to_blue, id_green_to_blue , id_green_to_red, id_clear_menu, id_show_menu, id_do_nothing, }; /*************** *********************************************/ /*************** * this is the automaton table ***************/ /*************** *********************************************/ const struct automaton automaton_table[max_states]= { /*state event action next state*/ {red, up, id_red_to_green,green}, {red, down, id_red_to_blue,blue}, {red, escape, id_clear_menu,off}, {red, set_menu, id_do_nothing, red}, {off, up, id_show_menu, red}, {off, down, id_show_menu, red}, {off, set_menu, id_show_menu, red}, {off, escape, id_do_nothing, red}, {blue, up, id_blue_to_red,red}, {blue, down, id_blue_to_green, green}, {blue, escape, id_clear_menu,off}, {blue, set_menu, id_do_nothing,red}, {green, up, id_green_to_blue, blue}, {green, down, id_green_to_red,red}, {green, escape, id_clear_menu,off}, {green, set_men u, id_do_nothing,red}, }; /*************** ************************************************** automaton run_au tomaton(automatonmenu) object: this routine scan the automaton depending on the state and event of the current automaton. 1
96/98 appendix - source files it return s the updated automaton. input: automat on output: automa ton => updated automaton **************** *************************************************/ automaton run_au tomaton(automatonmenu) { unsigned char count; save_page; spp(mmu_pg); save_dpr; dpr0_p = pag(automaton_table); dpr1_p = dpr0_p +1; count = 0; /* counter to scan au- tomaton table */ while(1) /* scan the automaton table to */ { /* find the corresponding one */ if (( menu.state == automaton_table[count].state) && ( menu.event == automaton_table[count] .event)){ /* get the state and event */ /* udate the automaton */ /* perform the action */ menu.actio n = automaton_table[count].action; menu.state = automaton_table[count].next_state; switch_a ction(menu.action); restore_ dpr; restore_ page; return(m enu); } else count++; if (count >= max_states) fatal(); } } void switch_action(unsignedchar name) { switch (name) { 1
97/98 appendix - source files case id_blue_to_green:blue_to_green();break; case id_blue_to_red:blue_to_red();break; case id_red_to_green:red_to_green(); break; case id_red_to_blue: red_to_blue();break; case id_green_to_blue: green_to_blue();break; case id_green_to_red:green_to_red();break; case id_clear_menu :clear_menu();break; case id_show_menu:show_menu(); break; case id_do_nothing:do_nothing();break; default: fatal(); break; } } void do_nothing(void) { } void fatal(void) { while(1); } 1
98/98 appendix - source files the present note which is for guidance only aims at providing customers with information regarding their products in order for them to save time. as a result, stmicroelectronics shall not be held liable for any direct, indirect or consequential damages with respect to any claims arising from the content of such a note and/or the use made by customers of the information contained herein in connexion with their products. information furnished is believed to be accurate and reliable. however, stmicroelectronics assumes no responsibility for the consequences of use of such information nor for any infringement of patents or other rights of third parties which may result from its use. n o license is granted by implication or otherwise under any patent or patent rights of stmicroelectronics. specifications mentioned in this publication are subject to change without notice. this publication supersedes and replaces all information previously supplied. stmicroelectronics products are not authorized for use as critical components in life support devices or systems without the express written approval of stmicroelectronics. the st logo is a registered trademark of stmicroelectronics ? 1998 stmicroelectronics - all rights reserved. purchase of i 2 c components by stmicroelectronics conveys a license under the philips i 2 c patent. rights to use these components in an i 2 c system is granted provided that the system conforms to the i 2 c standard specification as defined by philips. stmicroelectronics group of companies australia - brazil - canada - china - france - germany - italy - japan - korea - malaysia - malta - mexico - morocco - the netherlands - singapore - spain - sweden - switzerland - taiwan - thailand - united kingdom - u.s.a. http:/ /www.st.com 1


▲Up To Search▲   

 
Price & Availability of AN1075

All Rights Reserved © IC-ON-LINE 2003 - 2022  

[Add Bookmark] [Contact Us] [Link exchange] [Privacy policy]
Mirror Sites :  [www.datasheet.hk]   [www.maxim4u.com]  [www.ic-on-line.cn] [www.ic-on-line.com] [www.ic-on-line.net] [www.alldatasheet.com.cn] [www.gdcy.com]  [www.gdcy.net]


 . . . . .
  We use cookies to deliver the best possible web experience and assist with our advertising efforts. By continuing to use this site, you consent to the use of cookies. For more information on cookies, please take a look at our Privacy Policy. X